<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">



  
  
    
    
  <script src="/lib/pace/pace.min.js?v=1.0.2"></script>
  <link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet">







<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.2" rel="stylesheet" type="text/css">


  <meta name="keywords" content="Laravel,">





  <link rel="alternate" href="/atom.xml" title="King blog" type="application/atom+xml">




  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.2">






<meta name="description" content="Laravel Api REST 是所有 Web 应用都应该遵守的架构设计指导原则。 Representational State Transfer，翻译是”表现层状态转化”。 面向资源是 REST 最明显的特征，对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念，资源是以名词为核心来组织的，首先关注的是名词。REST 要求，必须通过统一的接口来对资源执行各种操作。对于每个资源只能">
<meta name="keywords" content="Laravel">
<meta property="og:type" content="article">
<meta property="og:title" content="Laravel">
<meta property="og:url" content="https://zhongxc.cc/d1159936.html">
<meta property="og:site_name" content="King blog">
<meta property="og:description" content="Laravel Api REST 是所有 Web 应用都应该遵守的架构设计指导原则。 Representational State Transfer，翻译是”表现层状态转化”。 面向资源是 REST 最明显的特征，对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念，资源是以名词为核心来组织的，首先关注的是名词。REST 要求，必须通过统一的接口来对资源执行各种操作。对于每个资源只能">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2021-04-20T08:53:29.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Laravel">
<meta name="twitter:description" content="Laravel Api REST 是所有 Web 应用都应该遵守的架构设计指导原则。 Representational State Transfer，翻译是”表现层状态转化”。 面向资源是 REST 最明显的特征，对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念，资源是以名词为核心来组织的，首先关注的是名词。REST 要求，必须通过统一的接口来对资源执行各种操作。对于每个资源只能">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    version: '5.1.2',
    sidebar: {"position":"right","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://zhongxc.cc/d1159936.html">





  <title>Laravel | King blog</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-right page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">King blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <h1 class="site-subtitle" itemprop="description"></h1>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://zhongxc.cc/d1159936.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="King">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/assets/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="King blog">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">Laravel</h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2021-04-20T16:53:29+08:00">
                2021-04-20
              </time>
            

            
              <span class="post-meta-divider">|</span>
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-check-o"></i>
              </span>
              
                <span class="post-meta-item-text">更新于&#58;</span>
              
              <time title="更新于" itemprop="dateModified" datetime="2021-04-20T16:53:29+08:00">
                2021-04-20
              </time>
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Laravel/" itemprop="url" rel="index">
                    <span itemprop="name">Laravel</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          
            <span class="post-meta-divider">|</span>
            <span class="page-pv"><i class="fa fa-eye"></i>
            <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>
            </span>
          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1>Laravel</h1>
<h2 id="api">Api</h2>
<p>REST 是所有 Web 应用都应该遵守的架构设计指导原则。 Representational State Transfer，翻译是”表现层状态转化”。</p>
<p>面向资源是 REST 最明显的特征，对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念，资源是以名词为核心来组织的，首先关注的是名词。REST 要求，必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。</p>
<a id="more"></a>
<h3 id="动作">动作</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">GET （SELECT）：从服务器检索特定资源，或资源列表</span><br><span class="line">POST （CREATE）：在服务器上创建一个新的资源</span><br><span class="line">PUT （UPDATE）：更新服务器上的资源，提供整个资源</span><br><span class="line">PATCH （UPDATE）：更新服务器上的资源，仅提供更改的属性</span><br><span class="line">DELETE （DELETE）：从服务器删除资源</span><br></pre></td></tr></table></figure>
<h3 id="命名">命名</h3>
<p>路径又称&quot;终点&quot;（endpoint），表示 API 的具体网址。</p>
<p>在 RESTful 架构中，每个网址代表一种资源（resource），所以网址中不能有动词，只能有名词，而且所用的名词往往与数据库的表名对应。一般来说，数据库中的表都是同种记录的&quot;集合&quot;（collection），所以 API 中的名词也应该使用复数。</p>
<p>举例来说，有一个 API 提供动物园（zoo）的信息，还包括各种动物和雇员的信息，则它的路径应该设计成下面这样。</p>
<p>接口尽量使用名词，禁止使用动词，下面是一些例子。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">GET         /zoos：列出所有动物园</span><br><span class="line">POST        /zoos：新建一个动物园</span><br><span class="line">GET         /zoos/ID：获取某个指定动物园的信息</span><br><span class="line">PUT         /zoos/ID：更新某个指定动物园的信息（提供该动物园的全部信息）</span><br><span class="line">PATCH       /zoos/ID：更新某个指定动物园的信息（提供该动物园的部分信息）</span><br><span class="line">DELETE      /zoos/ID：删除某个动物园</span><br><span class="line">GET         /zoos/ID/animals：列出某个指定动物园的所有动物</span><br><span class="line">DELETE      /zoos/ID/animals/ID：删除某个指定动物园的指定动物</span><br></pre></td></tr></table></figure>
<p>再比如，某个 URI 是/posts/show/1，其中 show 是动词，这个 URI 就设计错了，正确的写法应该是/posts/1，然后用 GET 方法表示 show。</p>
<h3 id="版本">版本</h3>
<p>应该将 API 的版本号放入 URL。如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://api.example.com/v1</span><br></pre></td></tr></table></figure>
<h3 id="过滤">过滤</h3>
<p>如果记录数量很多，服务器不可能都将它们返回给用户。API 应该提供参数，过滤返回结果。 下面是一些常见的参数。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">?limit=10：指定返回记录的数量</span><br><span class="line">?offset=10：指定返回记录的开始位置。</span><br><span class="line">?page_number=2&amp;page_size=100：指定第几页，以及每页的记录数。</span><br><span class="line">?sortby=name&amp;order=asc：指定返回结果按照哪个属性排序，以及排序顺序。</span><br><span class="line">?animal_type_id=1：指定筛选条件</span><br></pre></td></tr></table></figure>
<h3 id="状态码">状态码</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">200 OK - [GET]：服务器成功返回用户请求的数据，该操作是幂等的（Idempotent）。</span><br><span class="line">201 CREATED - [POST/PUT/PATCH]：用户新建或修改数据成功。</span><br><span class="line">202 Accepted - [*]：表示一个请求已经进入后台排队（异步任务）</span><br><span class="line">204 NO CONTENT - [DELETE]：用户删除数据成功。</span><br><span class="line">400 INVALID REQUEST - [POST/PUT/PATCH]：用户发出的请求有错误，服务器没有进行新建或修改数据的操作</span><br><span class="line">401 Unauthorized - [*]：表示用户没有权限（令牌、用户名、密码错误）。</span><br><span class="line">403 Forbidden - [*] 表示用户得到授权（与401错误相对），但是访问是被禁止的。</span><br><span class="line">404 NOT FOUND - [*]：用户发出的请求针对的是不存在的记录，服务器没有进行操作，该操作是幂等的。</span><br><span class="line">406 Not Acceptable - [GET]：用户请求的格式不可得（比如用户请求JSON格式，但是只有XML格式）。</span><br><span class="line">410 Gone -[GET]：用户请求的资源被永久删除，且不会再得到的。</span><br><span class="line">422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时，发生一个验证错误。</span><br><span class="line">429 Too Many Requests - 由于请求频次达到上限而被拒绝访问</span><br><span class="line">500 INTERNAL SERVER ERROR - [*]：服务器发生错误，用户将无法判断发出的请求是否成功。</span><br></pre></td></tr></table></figure>
<h3 id="响应格式">响应格式</h3>
<p>从可读性和通用性来讲 <code>JSON</code> 是最好的响应数据格式，下面是一个错误消息响应数据结构。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">	&apos;message&apos; =&gt; &apos;:message&apos;,</span><br><span class="line">	&apos;errors&apos; =&gt; &apos;:errors&apos;,</span><br><span class="line">	&apos;code&apos; =&gt; &apos;:code&apos;,</span><br><span class="line">	&apos;status_code&apos; =&gt; &apos;:status_code&apos;,</span><br><span class="line">	&apos;debug&apos; =&gt; &apos;:debug&apos;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>message：表示在 API 调用失败的情况下详细的错误信息，这个信息可以由客户端直接呈现给用户</li>
<li>errors：参数具体错误，比如字段较对错误内容</li>
<li>code：自定义错误码</li>
<li>status_code：http 状态码</li>
<li>debug：debug 调试信息</li>
</ul>
<blockquote>
<p>错误返回值根据情况进行删减</p>
</blockquote>
<h2 id="postman">Postman</h2>
<p>postman 可以高效的测试和维护接口。<a href="https://www.getpostman.com/apps" target="_blank" rel="noopener">https://www.getpostman.com/apps</a></p>
<h2 id="dingo">Dingo</h2>
<p>Dingo Api 是致力于提供给开发者一套工具，帮助你方便快捷的建造你自己的 API。这个包的目标是保持尽可能的灵活，它并不能覆盖所有的情况，也不能解决所有的问题。</p>
<p>官网：<a href="https://github.com/dingo/api/" target="_blank" rel="noopener">https://github.com/dingo/api/</a></p>
<p>文档：<a href="https://github.com/dingo/api/wiki/Configuration" target="_blank" rel="noopener">https://github.com/dingo/api/wiki/Configuration</a></p>
<h3 id="安装组件">安装组件</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require dingo/api:2.0.0-alpha2</span><br></pre></td></tr></table></figure>
<p>执行下面命令生成配置文件 <code>/config/api.php</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan vendor:publish</span><br></pre></td></tr></table></figure>
<h3 id="配置说明">配置说明</h3>
<p>配置统一定义在 <code>config/api.php</code> 文档中</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">#接口围绕：[x]本地和私有环境 [prs]公司内部app使用 [vnd]公开接口</span><br><span class="line">&apos;standardsTree&apos; =&gt; env(&apos;API_STANDARDS_TREE&apos;, &apos;x&apos;)</span><br><span class="line"></span><br><span class="line">#项目名称</span><br><span class="line">&apos;subtype&apos; =&gt; env(&apos;API_SUBTYPE&apos;, &apos;hdcms&apos;)</span><br><span class="line"></span><br><span class="line">#Api前缀 通过 www.hdcms.com/api 来访问 API。</span><br><span class="line">&apos;prefix&apos; =&gt; env(&apos;API_PREFIX&apos;, &apos;api&apos;)</span><br><span class="line"></span><br><span class="line">#api域名</span><br><span class="line">&apos;domain&apos; =&gt; env(&apos;API_DOMAIN&apos;, &apos;api.hdcms.com&apos;),</span><br><span class="line"></span><br><span class="line">#版本号</span><br><span class="line">&apos;version&apos; =&gt; env(&apos;API_VERSION&apos;, &apos;v1&apos;)</span><br><span class="line"></span><br><span class="line">#开发时开启DEBUG便于发现错误</span><br><span class="line">&apos;debug&apos; =&gt; env(&apos;API_DEBUG&apos;, false)</span><br></pre></td></tr></table></figure>
<blockquote>
<p>prefix 与 domain 只能二选一</p>
</blockquote>
<h3 id="接口版本">接口版本</h3>
<p>在 <code>routes/api.php</code> 文件定义</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">$api = app(\Dingo\Api\Routing\Router::class);</span><br><span class="line"></span><br><span class="line"><span class="comment">#默认配置指定的是v1版本，可以直接通过 &#123;host&#125;/api/version 访问到</span></span><br><span class="line">$api-&gt;version(<span class="string">'v1'</span>, <span class="function"><span class="keyword">function</span> <span class="params">($api)</span> </span>&#123;</span><br><span class="line">    $api-&gt;get(<span class="string">'version'</span>, <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">'v1'</span>;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">#如果v2不是默认版本，需要设置请求头</span></span><br><span class="line"><span class="comment">#Accept: application/[配置项 standardsTree].[配置项 subtype].v2+json</span></span><br><span class="line">$api-&gt;version(<span class="string">'v2'</span>, <span class="function"><span class="keyword">function</span> <span class="params">($api)</span> </span>&#123;</span><br><span class="line">    $api-&gt;get(<span class="string">'version'</span>, <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">'v2'</span>;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<h3 id="基础控制器">基础控制器</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:controller Api/Controller</span><br></pre></td></tr></table></figure>
<p>修改内容如下</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Http</span>\<span class="title">Controllers</span>\<span class="title">Api</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Dingo</span>\<span class="title">Api</span>\<span class="title">Routing</span>\<span class="title">Helpers</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Http</span>\<span class="title">Request</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Http</span>\<span class="title">Controllers</span>\<span class="title">Controller</span> <span class="title">as</span> <span class="title">SysController</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Controller</span> <span class="keyword">extends</span> <span class="title">SysController</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">Helpers</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="transformers">Transformers</h3>
<p>Transformers 允许你便捷地、始终如一地将对象转换为一个数组。通过使用一个 transformer 你可以对整数和布尔值，包括分页结果和嵌套关系进行类型转换。</p>
<h4 id="基本使用">基本使用</h4>
<p>一个 <strong>transformer</strong> 是一个类，它会获取原始数据并将返回一个格式化之后的标准数组。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">namespace App\Transformers;</span><br><span class="line"></span><br><span class="line">use App\User;</span><br><span class="line">use League\Fractal\TransformerAbstract;</span><br><span class="line"></span><br><span class="line">class UserTransformer extends TransformerAbstract</span><br><span class="line">&#123;</span><br><span class="line">    public function transform(User $user)</span><br><span class="line">    &#123;</span><br><span class="line">        return [</span><br><span class="line">            &apos;id&apos;   		=&gt; $user[&apos;id&apos;],</span><br><span class="line">            &apos;name&apos; 		=&gt; $user[&apos;name&apos;],</span><br><span class="line">            &apos;created_at&apos;=&gt; $user-&gt;created_at-&gt;toDateTimeString()</span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>返回单个数据</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">return $this-&gt;response-&gt;item(User::find(1),new UserTransformer());</span><br></pre></td></tr></table></figure>
<p><strong>返回集合</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">return $this-&gt;response-&gt;collection(User::get(),new UserTransformer());</span><br></pre></td></tr></table></figure>
<p><strong>分页数据</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">return $this-&gt;response-&gt;paginator(User::paginate(2),new UserTransformer());</span><br></pre></td></tr></table></figure>
<h4 id="include">include</h4>
<p>获取文章时我们希望获取文章的栏目数据，include 的特性就非常方便了。</p>
<p>下面是 ContentTransformer 中的定义，</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">class ContentTransformer extends TransformerAbstract</span><br><span class="line">&#123;</span><br><span class="line">	# 定义可以include可使用的字段</span><br><span class="line">    protected $availableIncludes = [&apos;category&apos;];</span><br><span class="line"></span><br><span class="line">    public function transform(Content $content)</span><br><span class="line">    &#123;</span><br><span class="line">        return [</span><br><span class="line">            &apos;id&apos;   =&gt; $content[&apos;id&apos;],</span><br><span class="line">            &apos;name&apos; =&gt; $content[&apos;title&apos;],</span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public function includeCategory(Content $content)</span><br><span class="line">    &#123;</span><br><span class="line">        return $this-&gt;item($content-&gt;category,new CategoryTransformer());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>当我们调用 <code>{host}/api/contents?include=category</code> 接口时，栏目数据也一并会返回</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">return $this-&gt;response-&gt;paginator(Content::paginate(1),new ContentTransformer());</span><br></pre></td></tr></table></figure>
<p>返回结果如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    &quot;data&quot;: [</span><br><span class="line">        &#123;</span><br><span class="line">            &quot;id&quot;: 1,</span><br><span class="line">            &quot;name&quot;: &quot;后盾人 人人做后盾&quot;,</span><br><span class="line">            &quot;category&quot;: &#123;</span><br><span class="line">                &quot;data&quot;: &#123;</span><br><span class="line">                    &quot;id&quot;: 2,</span><br><span class="line">                    &quot;name&quot;: &quot;编程&quot;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    ],</span><br><span class="line">    &quot;meta&quot;: &#123;</span><br><span class="line">        &quot;pagination&quot;: &#123;</span><br><span class="line">            &quot;total&quot;: 100,</span><br><span class="line">            &quot;count&quot;: 1,</span><br><span class="line">            &quot;per_page&quot;: 1,</span><br><span class="line">            &quot;current_page&quot;: 1,</span><br><span class="line">            &quot;total_pages&quot;: 100,</span><br><span class="line">            &quot;links&quot;: &#123;</span><br><span class="line">                &quot;next&quot;: &quot;http://laravel.local.com/api/contents?page=2&quot;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="响应结果">响应结果</h3>
<p><strong>设置响应状态码</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">return $this-&gt;response-&gt;array(User::get())-&gt;setStatusCode(200);</span><br><span class="line">return response()-&gt;json([&apos;error&apos; =&gt; &apos;Unauthorized&apos;], 401);</span><br></pre></td></tr></table></figure>
<p><strong>错误响应</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">// 一个自定义消息和状态码的普通错误。</span><br><span class="line">return $this-&gt;response-&gt;error(&apos;This is an error.&apos;, 404);</span><br><span class="line"></span><br><span class="line">// 一个没有找到资源的错误，第一个参数可以传递自定义消息。</span><br><span class="line">return $this-&gt;response-&gt;errorNotFound();</span><br><span class="line"></span><br><span class="line">// 一个 bad request 错误，第一个参数可以传递自定义消息。</span><br><span class="line">return $this-&gt;response-&gt;errorBadRequest();</span><br><span class="line"></span><br><span class="line">// 一个服务器拒绝错误，第一个参数可以传递自定义消息。</span><br><span class="line">return $this-&gt;response-&gt;errorForbidden();</span><br><span class="line"></span><br><span class="line">// 一个内部错误，第一个参数可以传递自定义消息。</span><br><span class="line">return $this-&gt;response-&gt;errorInternal();</span><br><span class="line"></span><br><span class="line">// 一个未认证错误，第一个参数可以传递自定义消息。</span><br><span class="line">return $this-&gt;response-&gt;errorUnauthorized(&apos;帐号或密码错误&apos;);</span><br></pre></td></tr></table></figure>
<h3 id="限制请求数">限制请求数</h3>
<p>使用 <code>api.throttle</code>中间件结合 <code>limit、expires</code> 参数可实现接口次数限制。下面是定义在 <code>routes/api.php</code> 路由文件中的示例。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$api-&gt;version(&apos;v1&apos;, [&apos;namespace&apos; =&gt; &apos;\App\Api&apos;], function ($api) &#123;</span><br><span class="line">    $api-&gt;group([&apos;middleware&apos; =&gt; &apos;api.throttle&apos;, &apos;limit&apos; =&gt; 2, &apos;expires&apos; =&gt; 1], function ($api) &#123;</span><br><span class="line">        $api-&gt;get(&apos;user&apos;, &apos;UserController@all&apos;);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p>限制 1 分钟只能访问 2 次。</p>
<h3 id="身份验证">身份验证</h3>
<p>可以通过 <code>api.auth</code> 路由中间件来启用路由或者路由群组的保护，我们使用下面讲解的 jwt 组件完成接口验证。</p>
<p><strong>在所有的路由上启用</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$api-&gt;version(&apos;v1&apos;, [&apos;middleware&apos; =&gt; &apos;api.auth&apos;], function ($api) &#123;</span><br><span class="line">    // 在这个版本群组下的所有路由将进行身份验证。</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p><strong>特定的路由上启用</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$api-&gt;version(&apos;v1&apos;, function ($api) &#123;</span><br><span class="line">    $api-&gt;get(&apos;user&apos;, [&apos;middleware&apos; =&gt; &apos;api.auth&apos;, function () &#123;</span><br><span class="line">        // 这个路由将进行身份验证。</span><br><span class="line">    &#125;]);</span><br><span class="line"></span><br><span class="line">    $api-&gt;get(&apos;posts&apos;, function () &#123;</span><br><span class="line">        // 这个路由不会验证身份。</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p><strong>控制器上进行身份验证</strong></p>
<p><code>Laravel</code>可以在控制器里启用中间件。您可以在构造函数里使用 <code>middleware</code> 的方法。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">class UserController extends Illuminate\Routing\Controller</span><br><span class="line">&#123;</span><br><span class="line">    use Helpers;</span><br><span class="line"></span><br><span class="line">    public function __construct()</span><br><span class="line">    &#123;</span><br><span class="line">        $this-&gt;middleware(&apos;api.auth&apos;);</span><br><span class="line"></span><br><span class="line">        // 这个中间件只在  index  中启用</span><br><span class="line">        $this-&gt;middleware(&apos;api.auth&apos;, [&apos;only&apos; =&gt; [&apos;index&apos;]]);</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
<h2 id="jwt">Jwt</h2>
<p>Jwt 是高效简单的接口验证组件，使用非常广泛。</p>
<p>GitHub：<a href="https://github.com/tymondesigns/jwt-auth" target="_blank" rel="noopener">https://github.com/tymondesigns/jwt-auth</a></p>
<p>Packagist：<a href="https://packagist.org/packages/tymon/jwt-auth" target="_blank" rel="noopener">https://packagist.org/packages/tymon/jwt-auth</a></p>
<p>在线文档： <a href="http://jwt-auth.readthedocs.io/en/develop/quick-start/" target="_blank" rel="noopener">http://jwt-auth.readthedocs.io/en/develop/quick-start/</a></p>
<h3 id="安装组件-v2">安装组件</h3>
<p>目前 2.0 版本正在开发中还不可以正常使用，所以我们使用 1.0.2。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require tymon/jwt-auth:1.0.2</span><br></pre></td></tr></table></figure>
<p><strong>生成配置文件</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan vendor:publish</span><br></pre></td></tr></table></figure>
<p><strong>生成密钥</strong></p>
<p>这是用来给你的 token 签名的钥匙，使用以下命令生成一个密钥:</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan jwt:secret</span><br></pre></td></tr></table></figure>
<p>这将用 <code>JWT_SECRET=foobar</code> 更新.env 文件</p>
<h3 id="配置说明-v2">配置说明</h3>
<p>JWT 配置文件是 <code>config/jwt.php</code>，下面有部分配置项进行说明：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">令牌过期时间(单位分钟)，设置null为永不过期</span></span><br><span class="line">'ttl' =&gt; env('JWT_TTL', 60)</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash">刷新令牌时间(单位分钟)，设置为null可永久随时刷新</span></span><br><span class="line">'refresh_ttl' =&gt; env('JWT_REFRESH_TTL', 20160)</span><br></pre></td></tr></table></figure>
<h3 id="更新用户模型">更新用户模型</h3>
<p>首先，您需要在用户模型上实现 <code>Tymon\JWTAuth\Contracts\JWTSubject</code> 契约，它要求您实现两个方法 <code>getJWTIdentifier()</code> 和 <code>getJWTCustomClaims()</code>。</p>
<p>下面的示例应该能让您了解这可能是什么样子的。显然，您应该根据需要进行任何更改，以满足自己的需要。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">&lt;?php</span><br><span class="line"></span><br><span class="line">namespace App;</span><br><span class="line"></span><br><span class="line">use Tymon\JWTAuth\Contracts\JWTSubject;</span><br><span class="line">use Illuminate\Notifications\Notifiable;</span><br><span class="line">use Illuminate\Foundation\Auth\User as Authenticatable;</span><br><span class="line"></span><br><span class="line">class User extends Authenticatable implements JWTSubject</span><br><span class="line">&#123;</span><br><span class="line">    use Notifiable;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取将存储在JWT主题声明中的标识符.</span><br><span class="line">     * 就是用户表主键 id</span><br><span class="line">     *</span><br><span class="line">     * @return mixed</span><br><span class="line">     */</span><br><span class="line">    public function getJWTIdentifier()</span><br><span class="line">    &#123;</span><br><span class="line">        return $this-&gt;getKey();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 返回一个键值数组，其中包含要添加到JWT的任何自定义声明.</span><br><span class="line">     *</span><br><span class="line">     * @return array</span><br><span class="line">     */</span><br><span class="line">    public function getJWTCustomClaims()</span><br><span class="line">    &#123;</span><br><span class="line">        return [];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="配置验证守卫">配置验证守卫</h3>
<p>修改 <code>config/auth.php</code> 文件以使用 jwt 保护来为接口身份验证提供支持。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&apos;guards&apos; =&gt; [</span><br><span class="line">	&apos;web&apos; =&gt; [</span><br><span class="line">		&apos;driver&apos; =&gt; &apos;session&apos;,</span><br><span class="line">		&apos;provider&apos; =&gt; &apos;users&apos;,</span><br><span class="line">	],</span><br><span class="line">	&apos;api&apos; =&gt; [</span><br><span class="line">		&apos;driver&apos; =&gt; &apos;jwt&apos;,</span><br><span class="line">		&apos;provider&apos; =&gt; &apos;users&apos;,</span><br><span class="line">	],</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
<p>修改 dingo 配置文件 <code>config/api.php</code> 文件中的身份验证提供者</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'auth'</span> =&gt; [</span><br><span class="line">	<span class="string">'jwt'</span> =&gt; \Dingo\Api\Auth\Provider\JWT::class,</span><br><span class="line">],</span><br></pre></td></tr></table></figure>
<h3 id="验证操作">验证操作</h3>
<p><strong>路由定义</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$api = app(\Dingo\Api\Routing\Router::class);</span><br><span class="line">$api-&gt;version(<span class="string">'v1'</span>, [<span class="string">'namespace'</span> =&gt; <span class="string">'App\Http\Controllers\Api'</span>,], <span class="function"><span class="keyword">function</span> <span class="params">($api)</span> </span>&#123;</span><br><span class="line">    $api-&gt;post(<span class="string">'login'</span>, <span class="string">'AuthController@login'</span>);</span><br><span class="line">    $api-&gt;get(<span class="string">'logout'</span>, <span class="string">'AuthController@logout'</span>);</span><br><span class="line">    $api-&gt;get(<span class="string">'me'</span>, <span class="string">'AuthController@me'</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p><strong>控制器定义</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AuthController</span> <span class="keyword">extends</span> <span class="title">Controller</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">    	<span class="comment">// 除login外都需要验证</span></span><br><span class="line">        <span class="keyword">$this</span>-&gt;middleware(<span class="string">'auth:api'</span>, [<span class="string">'except'</span> =&gt; [<span class="string">'login'</span>]]);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//登录获取token</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">login</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        $credentials = request([<span class="string">'email'</span>, <span class="string">'password'</span>]);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!$token = auth(<span class="string">'api'</span>)-&gt;attempt($credentials)) &#123;</span><br><span class="line">			<span class="keyword">return</span> <span class="keyword">$this</span>-&gt;response-&gt;errorUnauthorized(<span class="string">'帐号或密码错误'</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;respondWithToken($token);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//获取用户资料</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">me</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> response()-&gt;json(auth(<span class="string">'api'</span>)-&gt;user());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//销毁token</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">logout</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        auth(<span class="string">'api'</span>)-&gt;logout();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> response()-&gt;json([<span class="string">'message'</span> =&gt; <span class="string">'Successfully logged out'</span>]);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//刷新token</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">refresh</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;respondWithToken(auth(<span class="string">'api'</span>)-&gt;refresh());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//响应token</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">respondWithToken</span><span class="params">($token)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> response()-&gt;json([</span><br><span class="line">            <span class="string">'access_token'</span> =&gt; $token,</span><br><span class="line">            <span class="string">'token_type'</span>   =&gt; <span class="string">'bearer'</span>,</span><br><span class="line">            <span class="string">'expires_in'</span>   =&gt; auth(<span class="string">'api'</span>)-&gt;factory()-&gt;getTTL() * <span class="number">60</span>,</span><br><span class="line">        ]);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用令牌">使用令牌</h3>
<p>当请求需要验证的 api 时必须带有 token，下面是使用 header 头携带令牌数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Authorization: Bearer 令牌数据</span><br></pre></td></tr></table></figure>
<h2 id="laravel">Laravel</h2>
<h2 id="介绍">介绍</h2>
<p>Laravel 是一套简洁、优雅的 PHP Web 开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来；它可以帮你构建一个完美的网络 APP，而且每行代码都可以简洁、富于表达力。</p>
<p>Laravel 是 基于 PHP 语言的 Web 开源框架，采用了 MVC 的架构模式，在 2011 年 6 月正式发布了首个版本。 深度集成 PHP 强大的扩展包（Composer）生态与 PHP 开发者广大的受众群，让 Laravel 在发布之后的短短几年时间得到了极其迅猛的发展。我们通过 Google Trends 提供的趋势图（图 1.1）可以看出，Laravel 框架在过去十年，其增长速度迅猛。</p>
<h2 id="版本-v2">版本</h2>
<p><strong>Lts</strong></p>
<p>Long-Term Support,长期技术支持（版本），该版本拥有较长的维护周期，是商业项目优先考虑使用的版本。</p>
<p><strong>常规版</strong></p>
<p>提供 6 个月的 bug 修复，维护周期短但功能较新，学习为了使用新功能可采用这个版本。</p>
<h2 id="全新安装">全新安装</h2>
<p>使用 Composer 安装 Laravel 框架</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer create-project --prefer-dist laravel/laravel blog</span><br></pre></td></tr></table></figure>
<p>安装完 Laravel 之后，你必须将 web 服务器更目录指向 <code>public</code> 目录。该目录下的 <code>index.php</code> 文件将作为所有进入应用程序的 HTTP 请求的前端控制器。</p>
<p>需要修改 <code>.env</code> 配置文件中的 <code>APP_NAME</code> 与 <code>APP_URL</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">APP_NAME=Laravel</span><br><span class="line">APP_URL=http://laravel.local.com</span><br></pre></td></tr></table></figure>
<h2 id="mysql-低版本">MySQL 低版本</h2>
<p>如果你是在版本低于 5.7.7 的 MySQL release 上创建索引，那就需要你手动配置迁移生成的默认字符串长度。</p>
<p>在 <strong>AppServiceProvider.php</strong> 文件里的 boot 方法里设置</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">boot</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    \Schema::defaultStringLength(<span class="number">191</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="下载团队项目">下载团队项目</h2>
<p>检出别人的项目时，因为.env、verdor、node_moduels 文件或目录是不提交到版本库的，造成检出后项目不能正常运行。需要以下几步处理：</p>
<ol>
<li>composer install</li>
<li>cnpm install</li>
<li>复制 .env.example 文件为 .env 文件</li>
<li>执行 <code>php artisan key:generate</code> 生成应用秘钥</li>
<li>修改 .env 配置文件其他数据为你网站数据（比如数据库配置等）</li>
</ol>
<h2 id="基本使用-v2">基本使用</h2>
<p><strong>路由</strong></p>
<p>Laravel 的路由类型很多，先看路由的基础使用</p>
<p>修改 <code>routes/web.php</code> 路由表文件</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Route::get(<span class="string">'/home'</span>, <span class="string">'TestController@home'</span>);</span><br><span class="line">Route::get(<span class="string">'/lists'</span>, <span class="string">'TestController@lists'</span>);</span><br><span class="line">Route::get(<span class="string">'/show'</span>, <span class="string">'TestController@show'</span>);</span><br></pre></td></tr></table></figure>
<p><strong>控制器</strong></p>
<p>创建控制器命令</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artian make:controller TestController</span><br></pre></td></tr></table></figure>
<p>创建的控制器内容如下</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Http</span>\<span class="title">Controllers</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Http</span>\<span class="title">Request</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestController</span> <span class="keyword">extends</span> <span class="title">Controller</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">home</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">__METHOD__</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">lists</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">__METHOD__</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">show</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">__METHOD__</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>浏览器中访问<code>http://laravel.kk/lists</code>显示内容如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">App\Http\Controllers\TestController::lists</span><br></pre></td></tr></table></figure>
<p>以上就是 laravel 中基本路由与控制器的操作流程。</p>
<h2 id="视图">视图</h2>
<p>视图就是我们显示的页面，视图保存在 <code>resources/views</code> 文件夹中。</p>
<p><strong>继承</strong></p>
<p>模版继承是为了公用相同页面的代码，减少代码冗余</p>
<p>下面定义 <strong>views/layouts/master.blade.php</strong> 文件</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span></span><br><span class="line">      @yield('title', '后盾人')</span><br><span class="line">    <span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    @yield('content')</span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>然后在子模板中引入父模板，并使用 section 替换父模板中 yield 定义的占位内容。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">@extends(<span class="string">'layouts.master'</span>)</span><br><span class="line">@section(<span class="string">'title'</span>,<span class="string">'后盾人 - 首页'</span>)</span><br><span class="line">@section(<span class="string">'content'</span>)</span><br><span class="line">	&lt;h1&gt;首页<span class="number">1</span>&lt;/h1&gt;</span><br><span class="line">@endsection</span><br></pre></td></tr></table></figure>
<p><strong>include</strong></p>
<p>include 用于加载外部模板</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@<span class="keyword">include</span>(<span class="string">'user.show'</span>)</span><br></pre></td></tr></table></figure>
<p>被引入的视图会继承父视图中的所有数据，同时也可以向引入的视图传递额外的数组数据：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@<span class="keyword">include</span>(<span class="string">'view.name'</span>, [<span class="string">'some'</span> =&gt; <span class="string">'data'</span>])</span><br></pre></td></tr></table></figure>
<p><strong>includeIf</strong></p>
<p>当然，如果尝试使用 <code>@include</code> 去引入一个不存在的视图，Laravel 会抛出错误。如果想引入一个可能存在或可能不存在的视图，就使用 <code>@includeIf</code> 指令:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@includeIf(<span class="string">'view.name'</span>, [<span class="string">'some'</span> =&gt; <span class="string">'data'</span>])</span><br></pre></td></tr></table></figure>
<p><strong>includeWhen</strong></p>
<p>如果要根据给定的布尔条件 <code>@include</code> 视图，可以使用 <code>@includeWhen</code> 指令：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@includeWhen($boolean, <span class="string">'view.name'</span>, [<span class="string">'some'</span> =&gt; <span class="string">'data'</span>])</span><br></pre></td></tr></table></figure>
<p><strong>stack</strong></p>
<p>Blade 可以被推送到在其他视图或布局中的其他位置渲染的命名堆栈。这在子视图中指定所需的 JavaScript 库时非常有用：</p>
<p>父模版</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;!-- Head Contents --&gt;</span><br><span class="line">    @stack(<span class="string">'scripts'</span>)</span><br><span class="line">&lt;/head&gt;</span><br></pre></td></tr></table></figure>
<p>子模版</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@push(<span class="string">'scripts'</span>)</span><br><span class="line">    &lt;script src=<span class="string">"/example.js"</span>&gt;&lt;/script&gt;</span><br><span class="line">@endpush</span><br></pre></td></tr></table></figure>
<p><strong>component&amp;slot</strong></p>
<p>组件相比 @extends 更灵活些，下面是定义一个 <code>modal</code> 组件。</p>
<p>组件中的变量可以在调用组件时传参数</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@component(&apos;components.modal&apos;,[&apos;title&apos;=&gt;&apos;你好&apos;,&apos;url&apos;=&gt;route(&apos;home&apos;)])</span><br></pre></td></tr></table></figure>
<p>也可以使用 <code>slot</code> 标签赋值</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@slot(&apos;footer&apos;)</span><br><span class="line">&lt;button type=&quot;button&quot; data-dismiss=&quot;modal&quot; class=&quot;btn btn-secondary md-close&quot;&gt;cancel&lt;/button&gt;</span><br><span class="line">@endslot</span><br></pre></td></tr></table></figure>
<p><strong>示例</strong></p>
<p>定义一个模态框组件 <code>view/components/modal.blade.php</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&lt;form action=&quot;&#123;&#123;$url&#125;&#125;&quot; method=&quot;post&quot; &#123;!!isset($id)?&quot;id=\&quot;$id\&quot;&quot;:&apos;&apos;!!&#125;&gt;</span><br><span class="line">    @csrf</span><br><span class="line">    @isset($method) @method($method) @endif</span><br><span class="line">    &lt;div id=&quot;form-bp1&quot; tabindex=&quot;-1&quot; role=&quot;dialog&quot; class=&quot;modal fade colored-header colored-header-primary&quot;&gt;</span><br><span class="line">        &lt;div class=&quot;modal-dialog&quot;&gt;</span><br><span class="line">            &lt;div class=&quot;modal-content&quot;&gt;</span><br><span class="line">                &lt;div class=&quot;modal-header modal-header-colored&quot;&gt;</span><br><span class="line">                    &lt;h3 class=&quot;modal-title&quot;&gt;</span><br><span class="line">                        @isset($title) &#123;&#123;$title&#125;&#125; @endisset</span><br><span class="line">                    &lt;/h3&gt;</span><br><span class="line">                    &lt;button type=&quot;button&quot; data-dismiss=&quot;modal&quot; aria-hidden=&quot;true&quot; class=&quot;close md-close&quot;&gt;&lt;span class=&quot;mdi mdi-close&quot;&gt;&lt;/span&gt;&lt;/button&gt;</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">                &lt;div class=&quot;modal-body&quot;&gt;</span><br><span class="line">                    &#123;&#123;$slot&#125;&#125;</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">                &lt;div class=&quot;modal-footer&quot;&gt;</span><br><span class="line">                    @isset($footer)</span><br><span class="line">                        &#123;&#123;$footer&#125;&#125;</span><br><span class="line">                    @else</span><br><span class="line">                        &lt;button type=&quot;button&quot; data-dismiss=&quot;modal&quot; class=&quot;btn btn-secondary md-close&quot;&gt;关闭&lt;/button&gt;</span><br><span class="line">                        &lt;button type=&quot;button&quot; data-dismiss=&quot;modal&quot; class=&quot;btn btn-primary md-close&quot;&gt;保存&lt;/button&gt;</span><br><span class="line">                    @endif</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/form&gt;</span><br></pre></td></tr></table></figure>
<p>模板中调用 <code>modal</code> 组件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">@component(&apos;components.modal&apos;,[&apos;title&apos;=&gt;&apos;你好&apos;,&apos;url&apos;=&gt;route(&apos;home&apos;),&apos;method&apos;=&gt;&apos;PUT&apos;])</span><br><span class="line">&lt;div class=&quot;form-group row&quot;&gt;</span><br><span class="line">	&lt;label for=&quot;inputText3&quot; class=&quot;col-12 col-sm-3 col-form-label text-sm-right&quot;&gt;</span><br><span class="line">   		Input Text</span><br><span class="line"> 	&lt;/label&gt;</span><br><span class="line">	&lt;div class=&quot;col-12 col-sm-12 col-lg-6&quot;&gt;</span><br><span class="line">  		&lt;input id=&quot;inputText3&quot; type=&quot;text&quot; class=&quot;form-control form-control-sm&quot;&gt;</span><br><span class="line"> 	&lt;/div&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line">@slot(&apos;footer&apos;)</span><br><span class="line">    &lt;button type=&quot;button&quot; data-dismiss=&quot;modal&quot; class=&quot;btn btn-secondary md-close&quot;&gt;cancel&lt;/button&gt;</span><br><span class="line">    &lt;button type=&quot;button&quot; data-dismiss=&quot;modal&quot; class=&quot;btn btn-primary md-close&quot;&gt;save&lt;/button&gt;</span><br><span class="line">@endslot</span><br><span class="line">@endcomponent</span><br></pre></td></tr></table></figure>
<p><strong>动态视图目录</strong></p>
<p>有时我们需要经常改变视图目录</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$finder = app(<span class="string">'view'</span>)-&gt;getFinder();</span><br><span class="line">$finder-&gt;prependLocation(public_path(<span class="string">'templates/'</span>));</span><br></pre></td></tr></table></figure>
<h2 id="脚手架">脚手架</h2>
<p>安装 cnpm 使用国内镜像，安装速度快</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g cnpm --registry=https://registry.npm.taobao.org</span><br></pre></td></tr></table></figure>
<p>根据 packagist.json 安装前端库</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cnpm install</span><br><span class="line">cnpm install cross-env</span><br></pre></td></tr></table></figure>
<p>我们需要在 resources/assets 目录下的 js 与 css 目录中编写前端文件。</p>
<p>执行编译</p>
<p>需要执行编译操作，生成可供浏览器访问的文件，默认生成在 public/css 与 public/js 目录中</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run dev</span><br></pre></td></tr></table></figure>
<p>引入编译好的样式文件</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;link rel="stylesheet" href="/css/app.css"&gt;</span><br></pre></td></tr></table></figure>
<p>文件监听</p>
<p>每次修改都手动编译效率很低，执行以下命令后 Webpack 会在检测到文件更改时自动重新编译资源：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run watch</span><br></pre></td></tr></table></figure>
<p>在某些环境中，当文件更改时，Webpack 不会更新。如果系统出现这种情况，请考虑使用 <code>watch-poll</code> 命令：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run watch-poll</span><br></pre></td></tr></table></figure>
<p><strong>Bootstrap</strong></p>
<p>Laravel6.x 引入前端框架 Bootstrap &amp; jQuery</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /path/of/your/project</span><br><span class="line">composer require laravel/ui:^1.0 --dev  <span class="comment"># laravel6</span></span><br><span class="line">php artisan ui bootstrap</span><br><span class="line">php artisan ui bootstrap --auth</span><br><span class="line">npm install</span><br><span class="line">npm run dev</span><br></pre></td></tr></table></figure>
<p>在 app.scss 文件中定义：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@import &apos;~bootstrap/scss/bootstrap&apos;;</span><br></pre></td></tr></table></figure>
<h2 id="路由别名">路由别名</h2>
<p>进入路由跳转使用 <code>/home</code> 等形式可以正常进行，但如果我们有很多页面 使用了这种方式，后期我们将 <code>/home</code> 更改为了 <code>/root</code>，就要修改多个页面，显然不是很方式 。这时我们可以为路由起别名。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Route::get(<span class="string">'/home'</span>, <span class="string">'TestController@home'</span>)-&gt;name(<span class="string">'home'</span>);</span><br></pre></td></tr></table></figure>
<p>页面中使用调用即可</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;a class=&quot;nav-link&quot; href=&quot;&#123;&#123; route(&apos;home&apos;) &#125;&#125;&quot;&gt;网站首页&lt;/a&gt;</span><br></pre></td></tr></table></figure>
<h2 id="数据迁移">数据迁移</h2>
<p>迁移就像是数据库的版本控制, 允许团队简单轻松的编辑并共享应用的数据库表结构。</p>
<p>迁移文件默认保存在 <code>database/migrations</code> 文件夹中。</p>
<blockquote>
<p>如果使用 homestead 配置，要保证.env 配置正确，并保证主机客户端连接正常</p>
</blockquote>
<p><strong>运行迁移</strong></p>
<p>使用 Artisan 命令 <code>migrate</code> 方法来运行所有未完成的迁移：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan migrate</span><br></pre></td></tr></table></figure>
<p><strong>回滚迁移</strong></p>
<p>若要回滚最后一次迁移， 可以使用 <code>rollback</code> 命令。 此命令将回滚最后一次“迁移”的操作，其中可能包含多个迁移文件：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan migrate:rollback</span><br></pre></td></tr></table></figure>
<p><strong>关键外键约束</strong></p>
<p>下面是文章表 category_id 与栏目表的 id 关联约束设置，当栏目删除时栏目下的所有文章自动删除。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$table-&gt;unsignedInteger(<span class="string">'category_id'</span>)-&gt;comment(<span class="string">'栏目'</span>);</span><br><span class="line">$table-&gt;foreign(<span class="string">'category_id'</span>)-&gt;references(<span class="string">'id'</span>)-&gt;on(<span class="string">'categories'</span>)-&gt;onDelete(<span class="string">'cascade'</span>);</span><br></pre></td></tr></table></figure>
<p><strong>Seeder 自动填充测试数据</strong></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 运行填充器</span></span><br><span class="line">php artisan db:seed</span><br><span class="line"><span class="comment"># 单独运行某个填充器要加上--class=ArticleTableSeeder</span></span><br><span class="line">php artisan db:seed --class=ArticleTableSeeder</span><br><span class="line"><span class="comment"># 回滚并重新运行数据迁移</span></span><br><span class="line">php artisan migrate:refresh --seed</span><br></pre></td></tr></table></figure>
<h2 id="模型">模型</h2>
<p>Laravel 的 Eloquent ORM 提供了漂亮、简洁的 ActiveRecord 实现来和数据库交互。每个数据库表都有一个对应的「模型」用来与该表交互。你可以通过模型查询数据表中的数据，并将新记录添加到数据表中</p>
<p><strong>定义模型</strong></p>
<p>首先，创建一个 Eloquent 模型，默认生成的模型通常放在 <code>app</code> 目录中。</p>
<p>创建模型实例的最简单方法是使用 <a href="https://laravel-china.org/docs/laravel/5.6/artisan" target="_blank" rel="noopener">Artisan 命令</a> <code>make:model</code>：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:model Article</span><br></pre></td></tr></table></figure>
<p>如果要在生成模型时生成 <a href="https://laravel-china.org/docs/laravel/5.6/migrations" target="_blank" rel="noopener">数据库迁移</a> ，可以使用 <code>--migration</code> 或 <code>-m</code> 选项：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:model Article -m</span><br></pre></td></tr></table></figure>
<p><strong>数据库表名称</strong></p>
<p>可以通过在模型上定义 <code>table</code> 属性，来指定自定义数据表。如果不指定时使用模型名加 s，如 Article 对应表名为 articles</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> $table = <span class="string">'articles'</span>;</span><br></pre></td></tr></table></figure>
<p><strong>时间戳</strong></p>
<p>默认情况下，Eloquent 会默认数据表中存在 <code>created_at</code> 和 <code>updated_at</code> 这两个字段。如果你不需要这两个字段，则需要在模型内将 <code>$timestamps</code> 属性设置为 <code>false</code> ：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 该模型是否被自动维护时间戳</span></span><br><span class="line"><span class="keyword">public</span> $timestamps = <span class="keyword">false</span>;</span><br></pre></td></tr></table></figure>
<p><strong>本地作用域</strong></p>
<p>本地作用域能定义通用的约束集合以便在应用中复用。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询用户活跃类型 1 活跃 2 不活跃</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> \Illuminate\Database\Eloquent\Builder</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">scopeActive</span><span class="params">($query,$type=<span class="number">1</span>)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> $query-&gt;where(<span class="string">'active'</span>, $type);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>使用方法</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$users = App\User::active(<span class="number">1</span>)-&gt;get();</span><br></pre></td></tr></table></figure>
<p><strong>associate</strong></p>
<p>当更新 <code>belongsTo</code> 关联时，可以使用 <code>associate</code> 方法。此方法将会在子模型中设置外键：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$account = App\Account::find(<span class="number">10</span>);</span><br><span class="line">$user-&gt;account()-&gt;associate($account);</span><br><span class="line">$user-&gt;save();</span><br></pre></td></tr></table></figure>
<p><strong>软删除</strong></p>
<p>软件删除不是真正删除数据，只是在表中更改 deleted_at 状态完成，步骤如下：</p>
<p><strong>修改模型</strong></p>
<p>在模型上使用 <code>Illuminate\Database\Eloquent\SoftDeletes</code> trait 并把 <code>deleted_at</code> 字段加入 <code>$dates</code> 属性：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Database</span>\<span class="title">Eloquent</span>\<span class="title">SoftDeletes</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Video</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">SoftDeletes</span>;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>修改迁移文件</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Schema::create(<span class="string">'videos'</span>, <span class="function"><span class="keyword">function</span> <span class="params">(Blueprint $table)</span> </span>&#123;</span><br><span class="line">    $table-&gt;softDeletes();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p>现在，模型调用 <code>delete</code> 方法，当前日期时间会写入 <code>deleted_at</code> 字段。同时，查询出来的结果也会自动剔除软删除的模型。</p>
<p><strong>包括软删除的模型</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">App\Videos::withTrashed()-&gt;get();</span><br></pre></td></tr></table></figure>
<p><code>withTrashed</code> 方法也可以用在关联查询：</p>
<p><strong>只检索软删除的模型</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">App\Videos::onlyTrashed()-&gt;get();</span><br></pre></td></tr></table></figure>
<p><strong>恢复软删除模型</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">App\Videos::get()-&gt;restore();</span><br></pre></td></tr></table></figure>
<p><strong>永久删除</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$videos-&gt;forceDelete();</span><br></pre></td></tr></table></figure>
<blockquote>
<p>基本上软删除都可以用在关联操作中</p>
</blockquote>
<p><strong>Laravel &amp; Lumen 之 Eloquent ORM 使用速查-高级部分</strong></p>
<p><a href="https://segmentfault.com/a/1190000005792734" target="_blank" rel="noopener">https://segmentfault.com/a/1190000005792734</a></p>
<h2 id="登录历史跳转">登录历史跳转</h2>
<p>使用系统 auth 验证时，会自动 记录当前的 url，然后登录成功后使用以下代码就会跳转到来源地址。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> redirect()-&gt;intended(<span class="string">'/'</span>);</span><br></pre></td></tr></table></figure>
<p>inteded 方法参数默认为 <code>/</code> ，即没有历史来源时的跳转地址。</p>
<p>如果是自定义的验证，则需要使用以下代码记录来源地址。登录成功后还是使用上面代码跳转就可以了。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> redirect()-&gt;guest(route(<span class="string">'login'</span>))-&gt;with(<span class="string">'error'</span>, <span class="string">'请登录后操作'</span>);</span><br></pre></td></tr></table></figure>
<p>guest 参数必填即登录地址。</p>
<p>如果想自行定义登录后的回调地址使用下面方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">session([<span class="string">'url.intended'</span>=&gt;$request-&gt;getRequestUri()]);</span><br></pre></td></tr></table></figure>
<h2 id="分页">分页</h2>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$users = User::paginate(<span class="number">10</span>);</span><br></pre></td></tr></table></figure>
<p>模板中显示分页列表</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$users-&gt;links();</span><br></pre></td></tr></table></figure>
<p>分页时传递 GET 参数</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$users-&gt;appends(Request::except(<span class="string">'page'</span>))-&gt;links()</span><br></pre></td></tr></table></figure>
<h2 id="监听-sql">监听 SQL</h2>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">DB::enableQueryLog();</span><br><span class="line">执行语句</span><br><span class="line">dd(DB::getQueryLog());</span><br></pre></td></tr></table></figure>
<h2 id="tinker">TINKER</h2>
<p>使用 laravel 提供的 tinker 可以方便的在命令行进行调试。</p>
<p><strong>进入 tinker 环境</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan tinker</span><br></pre></td></tr></table></figure>
<p><strong>新增用户练习</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; <span class="keyword">use</span> \<span class="title">App</span>\<span class="title">User</span></span><br><span class="line">&gt;&gt;&gt; $<span class="title">user</span> = <span class="title">new</span> <span class="title">User</span></span><br><span class="line">&gt;&gt;&gt; $<span class="title">user</span>-&gt;<span class="title">create</span>(['<span class="title">name</span>'=&gt;'<span class="title">kings</span>','<span class="title">password</span>'=&gt;<span class="title">bcrypt</span>('123'),'<span class="title">email</span>'=&gt;'<span class="title">xxx</span>@<span class="title">qq</span>.<span class="title">com</span>'])</span><br></pre></td></tr></table></figure>
<blockquote>
<p>bcrypt 是用来对密码进行加密</p>
</blockquote>
<p><strong>查看用户</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; User::first()</span><br><span class="line">&gt;&gt;&gt; User::all()</span><br></pre></td></tr></table></figure>
<p><strong>修改记录</strong></p>
<p>下面使用 save 方法操作</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; $user = User::first()</span><br><span class="line">&gt;&gt;&gt; $user-&gt;name=<span class="string">'后盾人网站'</span></span><br><span class="line">&gt;&gt;&gt; $user-&gt;save()</span><br></pre></td></tr></table></figure>
<p>下面使用 update 批量更新</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; $user = User::first()</span><br><span class="line">&gt;&gt;&gt; $user-&gt;update([<span class="string">'name'</span>=&gt;<span class="string">'后盾人'</span>,<span class="string">'password'</span>=&gt;bcrypt(<span class="string">'admin'</span>)])</span><br></pre></td></tr></table></figure>
<h2 id="路由参数">路由参数</h2>
<p>比如我们定义下面的路由规则，其中 {user} 和 {name} 为路由中的参数变量</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Route::get(<span class="string">'/user/&#123;user&#125;/&#123;name&#125;'</span>,<span class="string">'UserController@show'</span>)-&gt;name(<span class="string">'user.show'</span>);</span><br></pre></td></tr></table></figure>
<p>控制器中获取参数方式如下:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> <span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Http</span>\<span class="title">Controllers</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Http</span>\<span class="title">Request</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserController</span> <span class="keyword">extends</span> <span class="title">Controller</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">show</span><span class="params">($user,$name)</span></span>&#123;</span><br><span class="line">    	dd($user.<span class="string">'='</span>.$name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="隐性路由模型绑定">隐性路由模型绑定</h2>
<p>Laravel 会自动解析定义在路由或控制器行为中与类型提示的变量名匹配的路由段名称的 Eloquent 模型。例如：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Route::get(<span class="string">'api/users/&#123;user&#125;'</span>, <span class="function"><span class="keyword">function</span> <span class="params">(App\User $user)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> $user-&gt;email;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p>在这个例子中，由于 <code>$user</code> 变量被类型提示为 Eloquent 模型 <code>App\User</code>，变量名称又与 URI 中的 <code>{user}</code> 匹配，因此，Laravel 会自动注入与请求 URI 中传入的 ID 匹配的用户模型实例。如果在数据库中找不到对应的模型实例，将会自动生成 404 异常。</p>
<h2 id="资源控制器">资源控制器</h2>
<p>Laravel 遵从 RESTful 架构的设计原则，将数据看做一个资源。Laravel 资源路由将典型的「CRUD」路由分配给具有单行代码的控制器。</p>
<p>使用 Artisan 命令 <code>make:controller</code> 来快速创建控制器：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:controller ArticleController --resource</span><br></pre></td></tr></table></figure>
<p>接下来，你可以给控制器注册一个资源路由：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Route::resource(<span class="string">'photos'</span>, <span class="string">'PhotoController'</span>);</span><br></pre></td></tr></table></figure>
<p><strong>资源控制器方法说明：</strong></p>
<table>
<thead>
<tr>
<th>动作</th>
<th>URI</th>
<th>行为</th>
<th>路由名称</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td><code>/photos</code></td>
<td>index</td>
<td>photos.index</td>
</tr>
<tr>
<td>GET</td>
<td><code>/photos/create</code></td>
<td>create</td>
<td>photos.create</td>
</tr>
<tr>
<td>POST</td>
<td><code>/photos</code></td>
<td>store</td>
<td>photos.store</td>
</tr>
<tr>
<td>GET</td>
<td><code>/photos/{photo}</code></td>
<td>show</td>
<td>photos.show</td>
</tr>
<tr>
<td>GET</td>
<td><code>/photos/{photo}/edit</code></td>
<td>edit</td>
<td>photos.edit</td>
</tr>
<tr>
<td>PUT/PATCH</td>
<td><code>/photos/{photo}</code></td>
<td>update</td>
<td>photos.update</td>
</tr>
<tr>
<td>DELETE</td>
<td><code>/photos/{photo}</code></td>
<td>destroy</td>
<td>photos.destroy</td>
</tr>
</tbody>
</table>
<blockquote>
<p>可以使用 <code>php artisan route:list</code> 查看已经定义的路由</p>
</blockquote>
<p><strong>指定资源模型</strong></p>
<p>如果你使用了路由模型绑定，并且想在资源控制器的方法中使用类型提示，你可以在生成控制器的时候使用 <code>--model</code> 选项：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:controller PhotoController --resource --model=Photo</span><br></pre></td></tr></table></figure>
<p><strong>伪造表单方法</strong></p>
<p>因为 HTML 表单不能生成 <code>PUT</code>、 <code>PATCH</code> 或者 <code>DELETE</code> 请求，所以你需要添加一个隐藏的 <code>_method</code> 输入字段来伪造这些 HTTP 动作。辅助函数 <code>method_field</code> 可以帮你创建这个字段：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123; method_field(&apos;PUT&apos;) &#125;&#125;</span><br></pre></td></tr></table></figure>
<h2 id="表单验证">表单验证</h2>
<p>下面是控制器中的 store 方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">store</span><span class="params">(Request $request)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;validate($request, [</span><br><span class="line">        <span class="string">'title'</span> =&gt; <span class="string">'required|unique:posts|max:255'</span>,</span><br><span class="line">        <span class="string">'body'</span> =&gt; <span class="string">'required'</span>,</span><br><span class="line">    ]);</span><br><span class="line">    <span class="comment">// 文章内容是符合规则的，存入数据库</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>常用规则</strong></p>
<table>
<thead>
<tr>
<th>规则</th>
<th>说明说明</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td>confirmed</td>
<td>验证的字段必须和 <code>foo_confirmation</code> 的字段值一致。例如，如果要验证的字段是 <code>password</code>，输入中必须存在匹配的 <code>password_confirmation</code> 字段。</td>
<td></td>
</tr>
<tr>
<td>size</td>
<td>验证的字段必须具有与给定值匹配的大小。对于字符串来说，<em>value</em> 对应于字符数。对于数字来说，<em>value</em> 对应于给定的整数值。对于数组来说， <em>size</em> 对应的是数组的 <code>count</code> 值。对文件来说，<em>size</em> 对应的是文件大小（单位 kb ）。</td>
<td></td>
</tr>
<tr>
<td>max</td>
<td>验证中的字段必须小于或等于 <em>value</em>。字符串、数字、数组或是文件大小的计算方式都用 <a href="https://laravel-china.org/docs/laravel/5.5/validation#rule-size" target="_blank" rel="noopener"><code>size</code></a> 方法进行评估。</td>
<td></td>
</tr>
<tr>
<td>min</td>
<td>验证中的字段必须具有最小值。字符串、数字、数组或是文件大小的计算方式都用 <a href="https://laravel-china.org/docs/laravel/5.5/validation#rule-size" target="_blank" rel="noopener"><code>size</code></a> 方法进行评估。</td>
<td></td>
</tr>
<tr>
<td>unique</td>
<td>unique:<em>table</em>,<em>column</em>,<em>except</em>,<em>idColumn</em>验证的字段在给定的数据库表中必须是唯一的。如果没有指定 <code>column</code>，将会使用字段本身的名称</td>
<td>'email' =&gt; 'unique:users,email_address'</td>
</tr>
<tr>
<td>required</td>
<td>验证的字段必须存在于输入数据中，而不是空。如果满足以下条件之一，则字段被视为「空」： 该值为 <code>null</code>. 该值为空字符串。 该值为空数组或空的 <code>可数</code> 对象。 该值为没有路径的上传文件。</td>
<td></td>
</tr>
<tr>
<td>email</td>
<td>验证的字段必须符合 e-mail 地址格式。</td>
<td></td>
</tr>
<tr>
<td>sometimes</td>
<td><strong>只有</strong>在该字段存在时， 才对字段执行验证</td>
<td></td>
</tr>
<tr>
<td>nullable</td>
<td>如果你不希望验证程序将 <code>null</code> 值视为无效的，那就将「可选」的请求字段标记为 <code>nullable</code>，也可以理解为有值时才验证。</td>
<td></td>
</tr>
</tbody>
</table>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$request-&gt;validate([</span><br><span class="line">    &apos;title&apos; =&gt; &apos;required|unique:posts|max:255&apos;,</span><br><span class="line">    &apos;body&apos; =&gt; &apos;required&apos;,</span><br><span class="line">    &apos;publish_at&apos; =&gt; &apos;nullable|date&apos;,</span><br><span class="line">]);</span><br></pre></td></tr></table></figure>
<p>在这个例子里，我们指定 <code>publish_at</code> 字段可以为 <code>null</code> 或者一个有效的日期格式。如果 <code>nullable</code> 的修饰词没有被添加到规则定义中，验证器会认为 <code>null</code> 是一个无效的日期格式。</p>
<blockquote>
<p>更多验证规则使用时请查阅手册 <a href="https://laravel.com/docs/6.x/validation" target="_blank" rel="noopener">https://laravel.com/docs/6.x/validation</a></p>
</blockquote>
<p><strong>显示验证错误</strong></p>
<p>如果表单验证失败，laravel 会向分配错误信息到 <code>$errors</code> 中，那么我们就可在模板中使用以下代码展示验证错误。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@if (count($errors) &gt; 0)</span><br><span class="line">    &lt;div class=&quot;alert alert-danger&quot;&gt;</span><br><span class="line">        &lt;ul&gt;</span><br><span class="line">            @foreach ($errors-&gt;all() as $error)</span><br><span class="line">                &lt;li&gt;&#123;&#123; $error &#125;&#125;&lt;/li&gt;</span><br><span class="line">            @endforeach</span><br><span class="line">        &lt;/ul&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">@endif</span><br></pre></td></tr></table></figure>
<p><strong>表单验证请求</strong></p>
<p>面对更复杂的验证情境中，你可以创建一个「表单请求」来处理更为复杂的逻辑。</p>
<p><strong>创建验证请示</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:request StoreBlogPost</span><br></pre></td></tr></table></figure>
<p>下面是一个示例</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserRequest</span> <span class="keyword">extends</span> <span class="title">FormRequest</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">authorize</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">rules</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> [</span><br><span class="line">            <span class="string">'name'</span>  =&gt; <span class="string">'required|between:5,20'</span>,</span><br><span class="line">            <span class="string">'email'</span> =&gt; <span class="string">"required|email|unique:users,email,"</span>.\Auth::user()-&gt;id,</span><br><span class="line">            <span class="string">'introduce'</span>=&gt;<span class="string">"required|max:80|min:10"</span>,</span><br><span class="line">            <span class="string">'avatar'</span>=&gt;<span class="string">'mimes:jpeg,bmp,png|dimensions:min_width=300,min_height=200'</span></span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">messages</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> [</span><br><span class="line">            <span class="string">'name.required'</span> =&gt; <span class="string">'昵称 不能为空'</span>,</span><br><span class="line">            <span class="string">'name.between'</span>=&gt;<span class="string">'昵称 必须介于 :min 与 :max 之间'</span></span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="表单函数">表单函数</h2>
<p><strong>csrf</strong></p>
<p>laravel （跨站请求伪造），Laravel 为了安全考虑，会让我们提供一个 token（令牌）来防止我们的应用受到 <a href="http://d.laravel-china.org/docs/5.5/routing#csrf-protection" target="_blank" rel="noopener">CSRF</a>（跨站请求伪造）的攻击。放置在表单（form）体内。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123;csrf_field()&#125;&#125;</span><br></pre></td></tr></table></figure>
<p><strong>old</strong></p>
<p><code>old</code>函数获取一次性存放在 session 中的值，用在表单的 value 属性中。这样当我们输出错误回调页面时，原来输入的值还存在。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;name&quot; value=&#123;&#123;old(&apos;name&apos;)&#125;&#125;&gt;</span><br></pre></td></tr></table></figure>
<h2 id="表单请求验证">表单请求验证</h2>
<p>面对更复杂的验证情境中，你可以创建一个「表单请求」来处理更为复杂的逻辑</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:request StoreBlogRequest</span><br></pre></td></tr></table></figure>
<p>新生成的类保存在 <code>app/Http/Requests</code> 目录下。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Http</span>\<span class="title">Requests</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Foundation</span>\<span class="title">Http</span>\<span class="title">FormRequest</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserRequest</span> <span class="keyword">extends</span> <span class="title">FormRequest</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="comment">// 权限验证</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">authorize</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 验证规则</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">rules</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> [</span><br><span class="line">            <span class="string">'name'</span>=&gt;<span class="string">'required|max:20'</span>,</span><br><span class="line">            <span class="string">'email'</span>=&gt;<span class="string">'required|email|unique:users|max:255'</span>,</span><br><span class="line">            <span class="string">'password'</span>=&gt;<span class="string">'required|confirmed|min:5'</span>,</span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 提示信息</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">messages</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> [</span><br><span class="line">            <span class="string">'name.required'</span> =&gt; <span class="string">'名称不能为空'</span>,</span><br><span class="line">            <span class="string">'email.required'</span>  =&gt; <span class="string">'邮箱不能为空'</span>,</span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在控制器的方法中依赖注入就可以使用了</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">store</span><span class="params">(UserRequest $request)</span></span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="重定向">重定向</h2>
<p><code>redirect</code> 函数返回一个 HTTP 重定向响应，如果调用时没有传入参数则返回 redirector 实例：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> redirect(<span class="string">'/home'</span>);</span><br><span class="line"><span class="keyword">return</span> redirect()-&gt;route(<span class="string">'route.name'</span>);</span><br></pre></td></tr></table></figure>
<p>传递路由参数</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$user = User::first()</span><br><span class="line"><span class="keyword">return</span> redirect()-&gt;route(<span class="string">'user.show'</span>,[$user]);</span><br></pre></td></tr></table></figure>
<p>假设路由规则为 <code>Route::get('user/show/{user}')</code> ，上例中的<code>[$user]</code>会自动提出 $user 模型对象的主键做为路由参数。</p>
<h2 id="闪存数据">闪存数据</h2>
<p>有时候你仅想在下一个请求之前在 Session 中存入数据，你可以使用 <code>flash</code> 方法。使用这个方法保存在 Session 中的数据，只会保留到下个 HTTP 请求到来之前，然后就会被删除。闪存数据主要用于短期的状态消息：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">session()-&gt;flash(<span class="string">'status'</span>, <span class="string">'Task was successful!'</span>);</span><br></pre></td></tr></table></figure>
<p>判断与获取闪存数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@if (session()-&gt;has($msg))</span><br><span class="line">	&#123;&#123;session()-&gt;get($msg)&#125;&#125;</span><br><span class="line">@endif</span><br></pre></td></tr></table></figure>
<p><strong>公共提示消息</strong></p>
<p>开发中经常用到消息提示，比如登录成功、退出成功等。使用 闪存数据定义一个公共的提示信息组件，就可以解决这个问题。</p>
<p><strong>控制器</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">store</span><span class="params">(UserRequest $request)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	session()-&gt;flash(<span class="string">'success'</span>,<span class="string">'注册成功，欢迎回家'</span>);</span><br><span class="line">	<span class="keyword">return</span> redirect()-&gt;route(<span class="string">'user.show'</span>,[$user]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>公共消息模板 <code>resource/view/layouts/_message.blade.php</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@foreach ([&apos;success&apos;,&apos;error&apos;,&apos;danger&apos;] as $msg)</span><br><span class="line">	@if (session()-&gt;has($msg))</span><br><span class="line">		&lt;div class=&quot;alert alert-&#123;&#123;$msg&#125;&#125;&quot;&gt;</span><br><span class="line">			&#123;&#123;session()-&gt;get($msg)&#125;&#125;</span><br><span class="line">		&lt;/div&gt;</span><br><span class="line">	@endif</span><br><span class="line">@endforeach</span><br></pre></td></tr></table></figure>
<p>需要用到的页面能过 <code>@include</code> 引入即可</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@include(&apos;layouts._message&apos;)</span><br></pre></td></tr></table></figure>
<h2 id="登录验证">登录验证</h2>
<p>使用 <code>Auth::attempt</code> 可以进行用户手动登录</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">authenticate</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (Auth::attempt([<span class="string">'email'</span> =&gt; $email, <span class="string">'password'</span> =&gt; $password])) &#123;</span><br><span class="line">		<span class="comment">// 认证通过...</span></span><br><span class="line">		<span class="keyword">return</span> redirect()-&gt;intended(<span class="string">'dashboard'</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>重定向器上的 <code>intended</code> 方法将重定向到用户尝试访问的 URL。如果该 URL 无效，会给该方法传递回退 URI。</p>
<p>传递历史表单，<code>withInput</code> 用于把历史表单返回给页面，这样页面中就可以使用 <code>old()</code> 函数显示历史输入数据了。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> redirect()-&gt;back()-&gt;withInput();</span><br></pre></td></tr></table></figure>
<p>完整示例</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LoginController</span> <span class="keyword">extends</span> <span class="title">Controller</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">store</span><span class="params">(Request $request)</span></span>&#123;</span><br><span class="line">		$user = <span class="keyword">$this</span>-&gt;validate($request,[</span><br><span class="line">			<span class="string">'email'</span>=&gt;<span class="string">'required'</span>,</span><br><span class="line">			<span class="string">'password'</span>=&gt;<span class="string">'required'</span>,</span><br><span class="line">		]);</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span>(Auth::attempt($user))&#123;</span><br><span class="line">			<span class="keyword">return</span> redirect(<span class="string">'/'</span>);</span><br><span class="line">		&#125;<span class="keyword">else</span>&#123;</span><br><span class="line">			session()-&gt;flash(<span class="string">'danger'</span>,<span class="string">'邮箱 或密码错误'</span>);</span><br><span class="line">			<span class="keyword">return</span> redirect()-&gt;back()-&gt;withInput();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>判断用户是否已经登录</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Auth::check();</span><br></pre></td></tr></table></figure>
<p>如果需要将现有用户进行登录，可以使用用户实例调用 <code>login</code> 方法。可以实现用户注册完就登录。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$user = User::first();</span><br><span class="line">Auth::login($user);</span><br></pre></td></tr></table></figure>
<p>用户退出</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">logout</span><span class="params">()</span></span>&#123;</span><br><span class="line">	Auth::logout();</span><br><span class="line">	session()-&gt;flash(<span class="string">'success'</span>,<span class="string">'退出成功'</span>);</span><br><span class="line">	<span class="keyword">return</span> redirect()-&gt;route(<span class="string">'login'</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>资源路由传参</strong></p>
<p>下面是资源路由中生成编辑资源 url 的方法。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;!! route(&apos;user.edit&apos;,$user-&gt;id) !!&#125;</span><br></pre></td></tr></table></figure>
<p><strong>历史跳转</strong></p>
<p><code>intended</code> 方法将重定向到用户尝试访问的 URL。如果该 URL 无效，会给该方法传递回退 URI。比如当用户编辑资料时，但用户没有登录，会先跳到用户登录页面。使用 intended 方法后登录成功后会回调到，编辑资料页面。如果没有历史，则跳转到 intended 指定的参数路由。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> redirect()-&gt;intended(<span class="string">'home'</span>);</span><br></pre></td></tr></table></figure>
<h2 id="模型事件">模型事件</h2>
<p>Eloquent 的模型触发了几个事件，可以在模型的生命周期的以下几点进行监控： <code>retrieved</code>、<code>creating</code>、<code>created</code>、<code>updating</code>、<code>updated</code>、<code>saving</code>、<code>saved</code>、<code>deleting</code>、<code>deleted</code>、<code>restoring</code>、<code>restored</code>。事件能在每次在数据库中保存或更新特定模型类时轻松地执行代码。</p>
<p>如果要给某个模型监听很多事件，则可以使用观察器将所有监听器分组到一个类中。观察器类里的方法名应该对应 Eloquent 中你想监听的事件。 每种方法接收 model 作为其唯一的参数。Laravel 没有为观察器设置默认的目录，所以你可以创建任何你喜欢你的目录来存放：</p>
<p><strong>定义事件</strong></p>
<p>下面是 User 模型的观察器</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">app</span>\<span class="title">Observers</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">User</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserObserver</span></span>&#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">creating</span><span class="params">(User $user)</span></span>&#123;</span><br><span class="line">		$user-&gt;active_token = str_random(<span class="number">20</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">saving</span><span class="params">(User $user)</span></span>&#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>声明事件</strong></p>
<p>在 AppServiceProvicer 服务提供者的 <code>boot</code> 方法执行以下代码</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">User::observe(UserObserver::class)</span><br></pre></td></tr></table></figure>
<p>或者在模型中定义</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Observers</span>\<span class="title">UserServer</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Notifications</span>\<span class="title">Notifiable</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Foundation</span>\<span class="title">Auth</span>\<span class="title">User</span> <span class="title">as</span> <span class="title">Authenticatable</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span> <span class="keyword">extends</span> <span class="title">Authenticatable</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">boot</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">parent</span>::boot();</span><br><span class="line">        User::observe(UserServer::class);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="权限策略">权限策略</h2>
<p>策略是在特定模型或者资源中组织授权逻辑的类。例如，针对用户的更新、修改操作就可以使用策略进行权限控制。</p>
<p><strong>创建策略</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:policy UserPolicy --model=User</span><br></pre></td></tr></table></figure>
<p>下面是一个策略类中的方法，$user为当前登录用户，$model 为调用策略时传递的用户模型实例。表示如果当前登录用户与用户实例相同可以更新。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">update</span><span class="params">(User $user, User $model)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">return</span> $user-&gt;id == $model-&gt;id;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>声明策略</strong></p>
<p>在 <code>app/Providers/AuthServiceProvider.php</code> 类的 <code>$policies</code> 属性中声明策略</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> $policies = [</span><br><span class="line">	<span class="string">'App\Model'</span> =&gt; <span class="string">'App\Policies\ModelPolicy'</span>,</span><br><span class="line">	<span class="string">'App\User'</span>=&gt;UserPolicy::class</span><br><span class="line">];</span><br></pre></td></tr></table></figure>
<p><strong>控制器中使用策略</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">$this</span>-&gt;authorize(<span class="string">'update'</span>, $user);</span><br><span class="line"><span class="comment">#后续业务代码..</span></span><br></pre></td></tr></table></figure>
<p><strong>友好显示</strong></p>
<p>当开启 DEBUG 时会抛出异常，关注后并定义 <code>403.blade.php</code> 模板后可以显示友好的提示。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">errors/403.blade.php</span><br></pre></td></tr></table></figure>
<h2 id="邮件">邮件</h2>
<p><strong>配置</strong></p>
<p>下面是针对 qq 邮箱的配置，其他邮箱请自行参考。</p>
<p>登录 <code>mail.qq.com</code> 你的邮箱。查找 <code>设置&gt;帐户&gt;POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务</code> 开启 pop3 并获取授权码。</p>
<p>可以在 <code>config/mail.php</code> 文件或.env 开发文件中设置，下面是.env 中的配置项</p>
<figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">MAIL_DRIVER</span>=smtp</span><br><span class="line"><span class="attr">MAIL_HOST</span>=smtp.qq.com</span><br><span class="line"><span class="attr">MAIL_PORT</span>=<span class="number">25</span></span><br><span class="line"><span class="attr">MAIL_USERNAME</span>=<span class="number">1028504601</span>@qq.com</span><br><span class="line"><span class="attr">MAIL_FROM_ADDRESS</span>=<span class="number">1028504601</span>@qq.com</span><br><span class="line"><span class="attr">MAIL_PASSWORD</span>=a334an2qgnjnoujbeaajj</span><br><span class="line"><span class="attr">MAIL_ENCRYPTION</span>=tls</span><br></pre></td></tr></table></figure>
<blockquote>
<p>MAIL_PASSWORD 为 QQ 邮箱提供的摄权码</p>
</blockquote>
<p><strong>Mailable</strong></p>
<p>在 Laravel 中，每种类型的邮件都代表一个「Mailable」对象。这些对象存储在 <code>app/Mail</code> 目录中。如果在你的应用中没有看见这个目录，别担心，在首次使用 <code>make:mail</code> 命令创建 Mailable 类时这个目录会被创建。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:mail regMail</span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> <span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Mail</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Bus</span>\<span class="title">Queueable</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Mail</span>\<span class="title">Mailable</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Queue</span>\<span class="title">SerializesModels</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Contracts</span>\<span class="title">Queue</span>\<span class="title">ShouldQueue</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RegMail</span> <span class="keyword">extends</span> <span class="title">Mailable</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">Queueable</span>, <span class="title">SerializesModels</span>;</span><br><span class="line">	<span class="comment">//公共属性可以模板中直接使用</span></span><br><span class="line">    <span class="keyword">public</span> $user;</span><br><span class="line">	<span class="comment">//构造函数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">($user)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;user = $user;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">build</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;view(<span class="string">'mails.reg'</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>发送</strong></p>
<p>执行以下代码就可以发送邮件了。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">\Mail::to(User::first())-&gt;send(new \App\Mail\RegMail(User::find(1)));</span><br></pre></td></tr></table></figure>
<blockquote>
<p>to：指发送给谁，字段中必须存在 email 和 name，send: 指使用的邮件处理器</p>
</blockquote>
<h2 id="集合">集合</h2>
<p><strong>contains</strong></p>
<p><code>contains</code> 方法判断集合是否包含给定的项目</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$collection = collect([<span class="string">'name'</span> =&gt; <span class="string">'Desk'</span>, <span class="string">'price'</span> =&gt; <span class="number">100</span>]);</span><br><span class="line">$collection-&gt;contains(<span class="string">'Desk'</span>);</span><br><span class="line"><span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">$collection-&gt;contains(<span class="string">'New York'</span>);</span><br><span class="line"><span class="comment">// false</span></span><br></pre></td></tr></table></figure>
<p><strong>pluck</strong></p>
<p><code>pluck</code> 方法可以获取集合中给定键对应的所有值：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$collection = collect([</span><br><span class="line">    [<span class="string">'product_id'</span> =&gt; <span class="string">'prod-100'</span>, <span class="string">'name'</span> =&gt; <span class="string">'Desk'</span>],</span><br><span class="line">    [<span class="string">'product_id'</span> =&gt; <span class="string">'prod-200'</span>, <span class="string">'name'</span> =&gt; <span class="string">'Chair'</span>],</span><br><span class="line">]);</span><br><span class="line">$plucked = $collection-&gt;pluck(<span class="string">'name'</span>);</span><br><span class="line">$plucked-&gt;all();</span><br><span class="line"><span class="comment">// ['Desk', 'Chair']</span></span><br></pre></td></tr></table></figure>
<p><strong>slice</strong></p>
<p><code>slice</code> 方法返回集合中给定值后面的部分：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$collection = collect([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>]);</span><br><span class="line">$slice = $collection-&gt;slice(<span class="number">4</span>);</span><br><span class="line">$slice-&gt;all();</span><br><span class="line"><span class="comment">// [5, 6, 7, 8, 9, 10]</span></span><br></pre></td></tr></table></figure>
<p><strong>has</strong></p>
<p><code>has</code> 方法判断集合中是否存在给定的键：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$collection = collect([<span class="string">'account_id'</span> =&gt; <span class="number">1</span>, <span class="string">'product'</span> =&gt; <span class="string">'Desk'</span>]);</span><br><span class="line">$collection-&gt;has(<span class="string">'product'</span>);</span><br><span class="line"><span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<p><strong>each</strong></p>
<p>each` 方法将迭代集合中的内容并将其传递到回调函数中：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$collection = $collection-&gt;each(<span class="function"><span class="keyword">function</span> <span class="params">($item, $key)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p><strong>count</strong></p>
<p><code>count</code> 方法返回该集合内的项目总数：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$collection = collect([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]);</span><br><span class="line">$collection-&gt;count();</span><br></pre></td></tr></table></figure>
<h2 id="多对多关联">多对多关联</h2>
<p><strong>attach</strong></p>
<p>我们假设一个用户可以拥有多个角色，并且每个角色都可以被多个用户共享。给某个用户附加一个角色是通过向中间表插入一条记录实现的，可以使用 <code>attach</code> 方法完成该操作：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$user = App\User::find(<span class="number">1</span>);</span><br><span class="line">$user-&gt;roles()-&gt;attach($roleId);</span><br></pre></td></tr></table></figure>
<p><strong>detach</strong></p>
<p>有时也需要移除用户的角色。可以使用 <code>detach</code>移除多对多关联记录。<code>detach</code> 方法将会移除中间表对应的记录；但是这 2 个模型都将会保留在数据库中：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 移除用户的一个角色...</span></span><br><span class="line">$user-&gt;roles()-&gt;detach($roleId);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 移除用户的所有角色...</span></span><br><span class="line">$user-&gt;roles()-&gt;detach();</span><br></pre></td></tr></table></figure>
<p><strong>sync</strong></p>
<p><code>sync</code> 方法接收一个 ID 数组以替换中间表的记录。中间表记录中，所有未在 ID 数组中的记录都将会被移除。所以该操作结束后，只有给出数组的 ID 会被保留在中间表中：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;roles()-&gt;sync([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);</span><br></pre></td></tr></table></figure>
<p>如果你不想移除现有的 ID，可以使用 <code>syncWithoutDetaching</code> 方法：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;roles()-&gt;syncWithoutDetaching([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);</span><br></pre></td></tr></table></figure>
<p><strong>allRelatedIds</strong></p>
<p><code>allRelatedIds</code> 用来获取关联模型的 ID 集合。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;roles()-&gt;allRelatedIds();</span><br></pre></td></tr></table></figure>
<p><strong>toggle</strong></p>
<p><code>toggle</code> 方法用于「切换」给定 ID 数组的附加状态。 如果给定的 ID 已被附加在中间表中，那么它将会被移除，同样，如果如果给定的 ID 已被移除，它将会被附加：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;roles()-&gt;toggle([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);</span><br></pre></td></tr></table></figure>
<h2 id="消息通知">消息通知</h2>
<h3 id="创建通知"><strong>创建通知</strong></h3>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:notification FindPasswordNotify</span><br></pre></td></tr></table></figure>
<p>这个命令会在 <code>app/Notifications</code> 目录下生成一个新的通知类</p>
<h3 id="数据库通知">数据库通知</h3>
<p><code>database</code> 通知渠道在一张数据库表里存储通知信息。该表以自定义的 JSON 格式，存储如通知类型等描述通知的信息。需要先创建一个数据库表来存放这些通知。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">php artisan notifications:table</span><br><span class="line"></span><br><span class="line">php artisan migrate</span><br></pre></td></tr></table></figure>
<p>修改通知类的 <code>via</code> 方法为数据库通知</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">via</span><span class="params">($notifiable)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">return</span> [<span class="string">'database'</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>然后定义 <code>toArray</code> 方法返回用于储存到数据表中的通知数据。</p>
<p><strong>存取通知</strong></p>
<p>Laravel 的默认模型 <code>App\User</code> 已经引入了 Trait <code>Illuminate\Notifications\Notifiable</code> ，它包含了一个 Eloquet 关系 <code>notifications</code> ，可以为实体返回通知。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$user = App\User::find(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">foreach</span> ($user-&gt;notifications <span class="keyword">as</span> $notification) &#123;</span><br><span class="line">    <span class="keyword">echo</span> $notification-&gt;type;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果你仅仅想检索所有「未读」通知，你需要使用 <code>unreadNotifications</code> 关系。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$user = App\User::find(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">foreach</span> ($user-&gt;unreadNotifications <span class="keyword">as</span> $notification) &#123;</span><br><span class="line">    <span class="keyword">echo</span> $notification-&gt;type;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>通知标记已读</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$user = App\User::find(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">foreach</span> ($user-&gt;unreadNotifications <span class="keyword">as</span> $notification) &#123;</span><br><span class="line">    $notification-&gt;markAsRead();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>你可以直接使用 <code>markAsRead</code> 方法操作一个通知集合，而不是遍历处理每个通知：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;unreadNotifications-&gt;markAsRead();</span><br></pre></td></tr></table></figure>
<h3 id="邮件通知">邮件通知</h3>
<p>修改通知类中的 <code>toMail</code> 与 <code>__construct</code> 方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">($token)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">$this</span>-&gt;token=$token;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">toMail</span><span class="params">($notifiable)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">return</span> (<span class="keyword">new</span> MailMessage)</span><br><span class="line">		-&gt;subject(<span class="string">'验证邮箱'</span>)</span><br><span class="line">		-&gt;greeting(config(<span class="string">'app.name'</span>))-&gt;line(<span class="string">'点击下面的链接重设密码'</span>)</span><br><span class="line">		-&gt;action(<span class="string">'重置密码'</span>,url(route(<span class="string">'password.change'</span>, <span class="keyword">$this</span>-&gt;token)))</span><br><span class="line">		-&gt;line(<span class="string">'感谢使用后盾人'</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>自定义模板</strong></p>
<p>你可以通过发布通知包的资源来修改 HTML 模板和纯文本模板。运行这个命令后，邮件通知模板就被放在了 <code>resources/views/vendor/notifications</code> 文件夹下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan vendor:publish --tag=laravel-notifications</span><br></pre></td></tr></table></figure>
<h3 id="发送通知">发送通知</h3>
<p><strong>使用 Notifiable Trait</strong></p>
<p>通知可以通过两种方法发送： <code>Notifiable</code> trait 的<code>notify</code> 方法或 <code>Notification</code> <a href="https://laravel-china.org/docs/laravel/5.6/facades" target="_blank" rel="noopener">facade</a>。首先，让我们探索使用 trait ：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> <span class="keyword">namespace</span> <span class="title">App</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Notifications</span>\<span class="title">Notifiable</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Foundation</span>\<span class="title">Auth</span>\<span class="title">User</span> <span class="title">as</span> <span class="title">Authenticatable</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span> <span class="keyword">extends</span> <span class="title">Authenticatable</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">Notifiable</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>默认的 <code>App\User</code> 模型中使用了这个 trait，它包含着一个可以用来发通知的方法：<code>notify</code> 。 <code>notify</code> 方法需要一个通知实例做参数：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Notifications</span>\<span class="title">InvoicePaid</span>;</span><br><span class="line"></span><br><span class="line">$user-&gt;notify(<span class="keyword">new</span> InvoicePaid($invoice));</span><br></pre></td></tr></table></figure>
<p><strong>使用 Notification Facade</strong></p>
<p>另外，你可以通过 <code>Notification</code> <code>facade</code> 来发送通知。它主要用在当你给多个可接收通知的实体发送通知的时候，比如给用户集合发通知。要用 facade 发送通知的话，要把可接收通知的实体和通知的实例传递给 <code>send</code> 方法：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Notification::send($users, <span class="keyword">new</span> InvoicePaid($invoice));</span><br></pre></td></tr></table></figure>
<h3 id="队列化通知">队列化通知</h3>
<p>发送通知可能很耗时，尤其是是当频道需要一个额外的 API 来发送通知。要加速你的应用响应时间，让你的通知继承 <code>ShouldQueue</code> 接口 并且在你的类中添加 <code>Queueable</code> trait。这些接口和 trait 已经被使用 <code>make:notification</code> 生成的所有通知引入了，所以你可以直接将他们添加到你的通知类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;?php</span><br><span class="line"></span><br><span class="line">namespace App\Notifications;</span><br><span class="line"></span><br><span class="line">use Illuminate\Bus\Queueable;</span><br><span class="line">use Illuminate\Notifications\Notification;</span><br><span class="line">use Illuminate\Contracts\Queue\ShouldQueue;</span><br><span class="line"></span><br><span class="line">class InvoicePaid extends Notification implements ShouldQueue</span><br><span class="line">&#123;</span><br><span class="line">    use Queueable;</span><br><span class="line"></span><br><span class="line">    // ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>做好一上操作并正常配置好队列后，系统将自动使用异步队列发送通知</p>
<h2 id="自定义函数">自定义函数</h2>
<p>有时我们需要加载自定义的函数文件，在 <code>composer.json</code> 文件中定义如下：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">"autoload": &#123;</span><br><span class="line">    ...</span><br><span class="line">    "files": ["bootstrap/helpers.php"]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>命令行执行 <code>composer dump-autoload</code> 重新生成加载配置</p>
<h2 id="redis">Redis</h2>
<p>在 homestead 中的 redis 允许的 IP 为 <code>127.0.0.1</code> 如果想让 windows 或 mac 的 GUI 工具可访问需要执行以下几步：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">修改redis配置文件，将127.0.0.1 改为 0.0.0.0</span></span><br><span class="line">sudo vim /etc/redis/redis.conf</span><br></pre></td></tr></table></figure>
<p>重起 redis 服务</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo service redis restart</span><br></pre></td></tr></table></figure>
<p>Gui 图形管理工具</p>
<ul>
<li>Mac <a href="http://getmedis.com/" target="_blank" rel="noopener">http://getmedis.com/</a></li>
<li>Win\Mac\Linux <a href="https://redisdesktop.com/" target="_blank" rel="noopener">https://redisdesktop.com/</a></li>
</ul>
<h2 id="队列">队列</h2>
<p>队列用于异步执行消耗时间多的工作，比如发送邮件，商城定单处理等操作，好处是可以快速为客户响应结果，具体处理异步后台操作。</p>
<p>下面的操作使用高效的 redis 完成处理，所以需要安装相应扩展包</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require "predis/predis:~1.0"</span><br></pre></td></tr></table></figure>
<p><strong>配置</strong></p>
<p>修改 <code>config/queue.php</code> 队列配置文件。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'default'</span> =&gt; env(<span class="string">'QUEUE_DRIVER'</span>, <span class="string">'sync'</span>),</span><br></pre></td></tr></table></figure>
<p>sync 为同步可更改为 database 或 redis 即为后台异步操作 ，需要先在 <code>config/database.php</code> 文件中将连接设置好。</p>
<p><strong>处理失败任务</strong></p>
<p>有时你的队列任务会失败。Laravel 包含了一个便捷的方式指定任务会被最大尝试的次数。在一个任务达到了它最大尝试次数后，它会被放入 <code>failed_jobs</code> 表。要创建 <code>failed_jobs</code> 表你可以使用 <code>queue:failed-table</code> 命令：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">php artisan queue:failed-table</span><br><span class="line">php artisan migrate</span><br></pre></td></tr></table></figure>
<p><strong>创建任务</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:job TestJob</span><br></pre></td></tr></table></figure>
<p>在生成的类中的 <code>handle</code> 方法设置任何具体动作，下面是一个简单的示例。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> $user;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">(User $user)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">$this</span>-&gt;user = $user;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">handle</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	sleep(<span class="number">6</span>);</span><br><span class="line">	file_put_contents(<span class="string">'a.php'</span>, var_export(<span class="keyword">$this</span>-&gt;user-&gt;toArray(),<span class="keyword">true</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>分发任务</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">TestJob::dispatch(User::find(<span class="number">1</span>));</span><br></pre></td></tr></table></figure>
<p><strong>队列处理器</strong></p>
<p>队列处理器用于执行推送到队列中的任务</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan queue:work</span><br></pre></td></tr></table></figure>
<blockquote>
<p>要使 <code>queue:work</code> 在后台运行需要使用下面讲到的 <code>Supervisor</code> （生产环境必用）</p>
</blockquote>
<p><strong>Laravel 队列监控面板</strong></p>
<p>Horizon 提供了一个漂亮的仪表盘，并且可以通过代码配置你的 Laravel Redis 队列，同时能够让你轻松地监控你的队列系统中诸如任务吞吐量，运行时间和失败任务等关键指标。</p>
<p>安装</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">composer require laravel/horizon</span><br><span class="line">php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"</span><br></pre></td></tr></table></figure>
<p>启动执行任务监听</p>
<p>只需一条命令语句即可启动队列执行进程。如果修改了任何代码需要重起 <code>horizon</code> 监听（需要在 homestead 系统执行）</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan horizon</span><br></pre></td></tr></table></figure>
<p>可以通过路由 <code>/horizon</code> 以图形界面查看任何状态</p>
<h2 id="supervisor">Supervisor</h2>
<p>Supervisor 是一个进程控制系统，用于让我们的队列任务在后台运行，并自动维护进行如果挂了就自动重起。</p>
<p><strong>修改配置文件</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vi /etc/supervisor/conf.d/laravel-worker.conf</span><br></pre></td></tr></table></figure>
<p>内容如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[program:laravel-worker]</span><br><span class="line">process_name=%(program_name)s_%(process_num)02d</span><br><span class="line">command=php /home/vagrant/code/hdcms-laravel/artisan queue:work --sleep=3 --tries=3</span><br><span class="line">autostart=true</span><br><span class="line">autorestart=true</span><br><span class="line">user=vagrant</span><br><span class="line">numprocs=8</span><br><span class="line">redirect_stderr=true</span><br><span class="line">stdout_logfile=/home/vagrant/code/hdcms-laravel/worker.log</span><br></pre></td></tr></table></figure>
<blockquote>
<p>注意 command 与 stdout_logfile 配置根据环境自行更改</p>
</blockquote>
<p><strong>运行</strong></p>
<p>依次执行下面命令加载配置并运行 <code>Supervisor</code></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo supervisorctl reread</span><br><span class="line"></span><br><span class="line">sudo supervisorctl update</span><br><span class="line"></span><br><span class="line">sudo supervisorctl start laravel-worker:*</span><br></pre></td></tr></table></figure>
<blockquote>
<p>这样我们就不需要执行 <code>php artisan queue:work</code> 命令了，交给 <code>Supervisor</code> 自动维护吧</p>
</blockquote>
<h2 id="repository">Repository</h2>
<p>组件库 Github：<a href="https://github.com/houdunwang/repository" target="_blank" rel="noopener">https://github.com/houdunwang/repository</a></p>
<p>Repository 模式主要思想是建立一个数据操作代理层，把 controller 里的数据操作剥离出来。</p>
<p>Repository 模式是架构模式，在设计架构时，才有参考价值。应用 Repository 模式所带来的好处，远高于实现这个模式所增加的代码。只要项目分层，都应当使用这个模式。</p>
<p>这样做有几个好处：</p>
<ul>
<li>把数据处理逻辑分离使得代码更容易维护</li>
<li>数据处理逻辑和业务逻辑分离，可以对这两个代码分别进行测试</li>
<li>减少代码重复</li>
<li>降低代码出错的几率</li>
<li>让 controller 代码的可读性大大提高</li>
</ul>
<h2 id="service-服务化">Service 服务化</h2>
<p>为了体现无尽的复用原则，应该将可用的功能服务器。比如邮箱发送、图片处理、上传功能等。</p>
<p>创建目录 <code>app\Services</code></p>
<p><strong>上传服务</strong></p>
<p><strong>创建服务类</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Services</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Symfony</span>\<span class="title">Component</span>\<span class="title">HttpFoundation</span>\<span class="title">File</span>\<span class="title">UploadedFile</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UploadService</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> $allow_ext = [<span class="string">'jpg'</span>, <span class="string">'jpeg'</span>, <span class="string">'png'</span>, <span class="string">'gif'</span>];</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">make</span><span class="params">(UploadedFile $file)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        $ext = strtolower($file-&gt;getClientOriginalExtension());</span><br><span class="line">        <span class="keyword">if</span> (in_array($ext, <span class="keyword">$this</span>-&gt;allow_ext)) &#123;</span><br><span class="line">            $dir     = <span class="string">'uploads/'</span>.date(<span class="string">'ymd'</span>);</span><br><span class="line">            $up_file = time().str_random(<span class="number">10</span>).<span class="string">'.'</span>.$ext;</span><br><span class="line">            $file-&gt;move($dir, $up_file);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> [<span class="string">'path'</span> =&gt; config(<span class="string">'app.url'</span>).<span class="string">'/'</span>.$dir.<span class="string">'/'</span>.$up_file];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>控制器中使用</strong></p>
<p>控制器中使用依赖注入服务就可正常使用了。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">editorImage</span><span class="params">(Request $request, UploadService $uploadService)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	$file = $uploadService-&gt;make($request-&gt;upload_file);</span><br><span class="line">	...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>图片处理服务</strong></p>
<p>阅读下面的 <code>插件&gt;图片处理</code> 文档安装图片处理插件。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Services</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Intervention</span>\<span class="title">Image</span>\<span class="title">Facades</span>\<span class="title">Image</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ImageService</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> $img;</span><br><span class="line">    <span class="keyword">protected</span> $file;</span><br><span class="line">    <span class="comment">//设置处理文件</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">file</span><span class="params">($file)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;file = $file;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;img  = Image::make($file);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//缩放</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">resize</span><span class="params">($width = null, $height = null)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;img-&gt;resize(</span><br><span class="line">            $width,</span><br><span class="line">            $height,</span><br><span class="line">            <span class="function"><span class="keyword">function</span> <span class="params">($constraint)</span> </span>&#123;</span><br><span class="line">                <span class="comment">//维护比例</span></span><br><span class="line">                $constraint-&gt;aspectRatio();</span><br><span class="line">                <span class="comment">//防止变大</span></span><br><span class="line">                $constraint-&gt;upsize();</span><br><span class="line">            &#125;</span><br><span class="line">        );</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//裁切</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">crop</span><span class="params">($w, $h)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;img-&gt;crop($w, $h);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//保存</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">save</span><span class="params">($file)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        $file = $file ? $file : <span class="keyword">$this</span>-&gt;file;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;img-&gt;save($file);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>控制器中使用</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">show</span><span class="params">(User $user,ImageService $image,Request $request)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	$image-&gt;file(<span class="string">'uploads/1.jpg'</span>)-&gt;resize(<span class="number">200</span>)-&gt;crop(<span class="number">200</span>,<span class="number">200</span>)-&gt;save(<span class="string">'uploads/4.jpg'</span>);</span><br><span class="line">	<span class="keyword">return</span> view(<span class="string">'user.show'</span>,compact(<span class="string">'user'</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="任务调度">任务调度</h2>
<p>在过去，开发者必须在服务器上为每个任务生成单独的 Cron 项目。而令人头疼的是任务调度不受源代码控制，而且必须通过 SSH 连接到服务器上来增加 Cron 项目。</p>
<p>编辑 crontab 计划任务（artisan 设置成你的项目地址）</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">export EDITOR=vi &amp;&amp; crontab -e</span><br><span class="line">* * * * * php /home/vagrant/code/bbs/artisan schedule:run &gt;&gt; /dev/null 2&gt;&amp;1</span><br></pre></td></tr></table></figure>
<h2 id="laravel-plugin">Laravel Plugin</h2>
<p>在 phpstorm 中安装 <code>laravel plugin</code> 插件.</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Settings &gt; Languages &amp; Frameworks &gt; PHP &gt; Laravel` 点击开启 `Enable for this project</span><br></pre></td></tr></table></figure>
<h2 id="laravel-ide-helper">laravel-ide-helper</h2>
<p>laravel-ide-helper 用于实现方便的代码提示功能。</p>
<p>使用 composer 安装插件</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require barryvdh/laravel-ide-helper</span><br></pre></td></tr></table></figure>
<p>在 <code>config\app.php</code> 文件 providers 添加</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,</span><br></pre></td></tr></table></figure>
<p>在 <strong>app/Providers/AppServiceProvider.php</strong> 文件中注册</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">register</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;app-&gt;environment() !== <span class="string">'production'</span>) &#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;app-&gt;register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>生成代码跟踪支持</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan ide-helper:generate</span><br></pre></td></tr></table></figure>
<p><strong>laravel artisan 命令提示</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">settings&gt;Tools&gt;Command Line Tool Support</span><br></pre></td></tr></table></figure>
<h2 id="多语言">多语言</h2>
<p><strong>语言包</strong></p>
<p>默认表单提示是英文的，我们可以安装中文语言包进行汉化。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require caouecs/laravel-lang:~4.0</span><br></pre></td></tr></table></figure>
<p>包含大多数语言，语言包位于<code>vendor/caouecs/larvel-lang/src</code> 目录中。</p>
<p><strong>使用</strong></p>
<ol>
<li>
<p>根据需要复制语言包到 <code>resources/lang</code> 目录中。</p>
</li>
<li>
<p>修改 <code>config/app.php</code> 配置文件</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'locale'</span> =&gt; <span class="string">'zh-CN'</span>,</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p><strong>JSON 语言包</strong></p>
<p>在 <code>resources/lang</code> 目录下定义 <code>zh-CN.json</code> 文件</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"Login"</span>: <span class="string">"登录"</span>,</span><br><span class="line">  <span class="attr">"Logout"</span>: <span class="string">"退出"</span>,</span><br><span class="line">  <span class="attr">"E-Mail Address"</span>: <span class="string">"邮箱"</span>,</span><br><span class="line">  <span class="attr">"Register"</span>: <span class="string">"注册"</span>,</span><br><span class="line">  <span class="attr">"Password"</span>: <span class="string">"密码"</span>,</span><br><span class="line">  <span class="attr">"Confirm Password"</span>: <span class="string">"确认密码"</span>,</span><br><span class="line">  <span class="attr">"Name"</span>: <span class="string">"帐号"</span>,</span><br><span class="line">  <span class="attr">"Remember Me"</span>: <span class="string">"记住我"</span>,</span><br><span class="line">  <span class="attr">"Forgot Your Password?"</span>: <span class="string">"找回密码"</span>,</span><br><span class="line">  <span class="attr">"Reset Password"</span>: <span class="string">"重置密码"</span>,</span><br><span class="line">  <span class="attr">"Send Password Reset Link"</span>: <span class="string">"发送重置邮件"</span>,</span><br><span class="line">  <span class="attr">"Reset Password Notification"</span>: <span class="string">"重置密码通知"</span>,</span><br><span class="line">  <span class="attr">"You are receiving this email because we received a password reset request for your account."</span>: <span class="string">"您收到这封邮件是因为我们收到您的帐户密码重置请求。"</span>,</span><br><span class="line">  <span class="attr">"If you did not request a password reset, no further action is required."</span>: <span class="string">"如果没有要求重新设置密码，则不需要进一步的操作。"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在模板中就可以使用 <code>__('Login')</code> 调用了，Laravel 默认的登录模板大量使用了 JSON 语言包</p>
<h2 id="session">SESSION</h2>
<p>默认 Laravel 使用文件管理会话，下面是我们改为更高效的数据库管理。</p>
<p>创建数据表</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">php artisan session:table</span><br><span class="line">composer dump-autoload</span><br><span class="line">php artisan migrate</span><br></pre></td></tr></table></figure>
<p>修改.env 中的驱动</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line">SESSION_DRIVER=database</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
<h2 id="验证码">验证码</h2>
<p><a href="https://github.com/mewebstudio/captcha" target="_blank" rel="noopener">https://github.com/mewebstudio/captcha</a></p>
<p>安装</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">composer require mews/captcha</span><br><span class="line">php artisan vendor:publish --provider=&apos;Mews\Captcha\CaptchaServiceProvider&apos;</span><br></pre></td></tr></table></figure>
<p>配置文件 <code>config/captcha.php</code></p>
<p>使用</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">#前台</span><br><span class="line">&lt;img src=&quot;&#123;&#123; captcha_src(&apos;default&apos;) &#125;&#125;&quot; onclick=&quot;this.src=&apos;/captcha/default?_&apos;+Math.random()&quot;&gt;</span><br><span class="line"></span><br><span class="line">#后台验证</span><br><span class="line">$rules = [&apos;captcha&apos; =&gt; &apos;required|captcha&apos;];</span><br><span class="line">$validator = Validator::make(Input::all(), $rules);</span><br></pre></td></tr></table></figure>
<h2 id="用户认证">用户认证</h2>
<h3 id="重定向未认证用户">重定向未认证用户</h3>
<p>当 <code>auth</code> 中间件判定某个用户未认证，会返回一个 JSON <code>401</code> 响应，或者，如果不是 Ajax 请求的话，将用户重定向到 <code>login</code> 命名路由。</p>
<p>你可以通过在 <code>app/Exceptions/Handler.php</code> 文件中定义一个 <code>unauthenticated</code> 方法来改变这一行为：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">IlluminateAuthAuthenticationException</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">unauthenticated</span><span class="params">($request, AuthenticationException $exception)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> $request-&gt;expectsJson()</span><br><span class="line">                ? response()-&gt;json([<span class="string">'message'</span> =&gt; $exception-&gt;getMessage()], <span class="number">401</span>)</span><br><span class="line">                : redirect()-&gt;guest(route(<span class="string">'login'</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="事件">事件</h3>
<p>Laravel 在认证过程中引发了各种各样的事件。你可以在 <code>EventServiceProvider</code> 中对这些事件做监听：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 应用程序的事件监听器映射。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> array</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> $listen = [</span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\Registered'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogRegisteredUser'</span>,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\Attempting'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogAuthenticationAttempt'</span>,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\Authenticated'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogAuthenticated'</span>,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\Login'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogSuccessfulLogin'</span>,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\Failed'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogFailedLogin'</span>,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\Logout'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogSuccessfulLogout'</span>,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\Lockout'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogLockout'</span>,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="string">'Illuminate\Auth\Events\PasswordReset'</span> =&gt; [</span><br><span class="line">        <span class="string">'App\Listeners\LogPasswordReset'</span>,</span><br><span class="line">    ],</span><br><span class="line">];</span><br></pre></td></tr></table></figure>
<h2 id="异常处理-excepton">异常处理 Excepton</h2>
<p>异常处理通常是防止未知错误产生所采取的处理措施。异常处理的好处是你不用再绞尽脑汁去考虑各种错误，这为处理某一类错误提供了一个很有效的方法，使编程效率大大提高。</p>
<h3 id="创建异常类">创建异常类</h3>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan artisan make:exception UploadException</span><br></pre></td></tr></table></figure>
<p>定义类内容如下</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Exceptions</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Exception</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Throwable</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UploadException</span> <span class="keyword">extends</span> <span class="title">Exception</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">(string $message = <span class="string">""</span>, int $code = <span class="number">403</span>, Throwable $previous = null)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">parent</span>::__construct($message, $code, $previous);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">//报告或者通过日志记录一个异常</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">report</span><span class="params">(Exception $exception)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">parent</span>::report($exception);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">//将异常通过 Http 返回</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">render</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> response()-&gt;json([<span class="string">'message'</span> =&gt; <span class="keyword">$this</span>-&gt;getMessage(), <span class="string">'code'</span> =&gt; <span class="number">403</span>], <span class="keyword">$this</span>-&gt;code);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="异常日志">异常日志</h3>
<p>当发生异常时会在 <code>storage/logs/laravel.log</code> 文件中记录异常。</p>
<p>如果不想执行异常记录需要在 <code>app/Exceptions/Handler.php</code> 异常处理器文件的 <code>$dontReport</code> 属性声明。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Handler</span> <span class="keyword">extends</span> <span class="title">ExceptionHandler</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">   ...</span><br><span class="line">   <span class="keyword">protected</span> $dontReport = [</span><br><span class="line">   	UploadException::class,</span><br><span class="line">   ];</span><br><span class="line">   ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="全站动态">全站动态</h2>
<p>使用 <a href="https://github.com/spatie/laravel-activitylog" target="_blank" rel="noopener">https://github.com/spatie/laravel-activitylog</a> 组件构成，可查看 <a href="https://docs.spatie.be/laravel-activitylog/v3/introduction" target="_blank" rel="noopener">https://docs.spatie.be/laravel-activitylog/v3/introduction</a> 文档学习使用该组件。</p>
<p>安装组件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require spatie/laravel-activitylog</span><br></pre></td></tr></table></figure>
<p>创建数据迁移文件并执行</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="migrations"</span><br><span class="line"></span><br><span class="line">php artisan migrate</span><br></pre></td></tr></table></figure>
<h3 id="记录动态">记录动态</h3>
<p><strong>基本使用</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">activity()</span><br><span class="line">   -&gt;performedOn($someContentModel)<span class="comment">//主题比如评论模型</span></span><br><span class="line">   -&gt;causedBy($userModel)<span class="comment">//用户模型，不设置时为当前登录用户</span></span><br><span class="line">   -&gt;log(<span class="string">'edited'</span>);</span><br></pre></td></tr></table></figure>
<p><strong>设置自定义属性</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">activity()</span><br><span class="line">   -&gt;performedOn($someContentModel)</span><br><span class="line">   -&gt;withProperties([<span class="string">'key'</span> =&gt; <span class="string">'value'</span>])<span class="comment">//设置自定义属性</span></span><br><span class="line">   -&gt;log(<span class="string">'edited'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回最后动态</span></span><br><span class="line">$activity = Activity::all()-&gt;last();</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取用户模型</span></span><br><span class="line">$activity-&gt;causer</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取日志名</span></span><br><span class="line">$activity-&gt;log_name</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取属性</span></span><br><span class="line">$activity-&gt;getExtraProperty(<span class="string">'key'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取自定属性 'key' 为 'value' 的所有动态</span></span><br><span class="line">$activity-&gt;where(<span class="string">'properties-&gt;key'</span>, <span class="string">'value'</span>)-&gt;get();</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回模型实例</span></span><br><span class="line">$activity-&gt;subject;</span><br></pre></td></tr></table></figure>
<h3 id="记录模型事件">记录模型事件</h3>
<p>程序包可以自动记录事件，例如创建，更新和删除模型时。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Database</span>\<span class="title">Eloquent</span>\<span class="title">Model</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Spatie</span>\<span class="title">Activitylog</span>\<span class="title">Traits</span>\<span class="title">LogsActivity</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">NewsItem</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">LogsActivity</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> $fillable = [<span class="string">'name'</span>, <span class="string">'text'</span>];</span><br><span class="line"></span><br><span class="line">	<span class="comment">//设置动态记录的属性</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">static</span> $logAttributes = [<span class="string">'name'</span>, <span class="string">'text'</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果要记录<code>$fillable</code>对模型的所有属性的更改，可以<code>protected static $logFillable = true;</code></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">$newsItem = NewsItem::create([</span><br><span class="line">   <span class="string">'name'</span> =&gt; <span class="string">'original name'</span>,</span><br><span class="line">   <span class="string">'text'</span> =&gt; <span class="string">'Lorum'</span></span><br><span class="line">]);</span><br><span class="line"></span><br><span class="line">$activity = Activity::all()-&gt;last();</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回 'created'</span></span><br><span class="line">$activity-&gt;description;</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回创建的NewsItem实例</span></span><br><span class="line">$activity-&gt;subject;</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回模型NewsItem属性 ['attributes' =&gt; ['name' =&gt; 'original name', 'text' =&gt; 'Lorum']];</span></span><br><span class="line">$activity-&gt;changes();</span><br></pre></td></tr></table></figure>
<h3 id="自定义要记录的事件">自定义要记录的事件</h3>
<p>默认情况下，包将记录<code>created</code>，<code>updated</code>，<code>deleted</code>的事件。您可以通过<code>$recordEvents</code>在模型上设置属性来修改此行为。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Database</span>\<span class="title">Eloquent</span>\<span class="title">Model</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Spatie</span>\<span class="title">Activitylog</span>\<span class="title">Traits</span>\<span class="title">LogsActivity</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">NewsItem</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">LogsActivity</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//only the `deleted` event will get logged automatically</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">static</span> $recordEvents = [<span class="string">'created'</span>,<span class="string">'updated'</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="自定义日志名称">自定义日志名称</h3>
<p>指定<code>$logName</code>使模型使用除默认名称之外的其他名称。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Database</span>\<span class="title">Eloquent</span>\<span class="title">Model</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Spatie</span>\<span class="title">Activitylog</span>\<span class="title">Traits</span>\<span class="title">LogsActivity</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">NewsItem</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">LogsActivity</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">static</span> $logName = <span class="string">'system'</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="markdown-转-html">Markdown 转 HTML</h2>
<p>Parsedown 组件用于将 <code>markdown</code> 内容转为 <code>html</code></p>
<p><strong>安装组件</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require erusev/parsedown</span><br></pre></td></tr></table></figure>
<p><strong>模型中使用</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Article</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">   ...</span><br><span class="line">	<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getMarkdownAttribute</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        $Parsedown = <span class="keyword">new</span> \Parsedown();</span><br><span class="line">        <span class="keyword">return</span> $Parsedown-&gt;text(<span class="keyword">$this</span>[<span class="string">'content'</span>]);</span><br><span class="line">    &#125;</span><br><span class="line">    ..</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="角色权限">角色权限</h2>
<p><a href="https://docs.spatie.be/laravel-permission/v3/introduction/" target="_blank" rel="noopener">https://docs.spatie.be/laravel-permission/v3/introduction/</a></p>
<p><strong>安装</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">composer require spatie/laravel-permission</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash">生成迁移文件，根据业务需要可以随意添加表字段</span></span><br><span class="line">php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"</span><br><span class="line"></span><br><span class="line">php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"</span><br><span class="line"></span><br><span class="line">php artisan migrate</span><br></pre></td></tr></table></figure>
<p><strong>基本使用</strong></p>
<p>缓存角色和权限数据以加速性能。当你使用提供的方法来操作角色和权限时，缓存会自动为您重置：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;assignRole(<span class="string">'writer'</span>);</span><br><span class="line">$user-&gt;removeRole(<span class="string">'writer'</span>);</span><br><span class="line">$user-&gt;syncRoles(params);</span><br><span class="line">$role-&gt;givePermissionTo(<span class="string">'edit articles'</span>);</span><br><span class="line">$role-&gt;revokePermissionTo(<span class="string">'edit articles'</span>);</span><br><span class="line">$role-&gt;syncPermissions(params);</span><br><span class="line">$permission-&gt;assignRole(<span class="string">'writer'</span>);</span><br><span class="line">$permission-&gt;removeRole(<span class="string">'writer'</span>);</span><br><span class="line">$permission-&gt;syncRoles(params);</span><br></pre></td></tr></table></figure>
<p>但是，如果直接在数据库中操作“权限/角色”数据而不是调用提供的方法，则除非手动重置缓存，否则不会在应用程序中看到反映的更改。</p>
<p><strong>手动缓存重置</strong></p>
<p>缓存角色和权限数据以加速性能。当你使用提供的方法来操作角色和权限时，缓存会自动为您重置。</p>
<p>要手动重置此软件包的缓存，请运行：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan cache:forget spatie.permission.cache</span><br></pre></td></tr></table></figure>
<p>代码删除缓存</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">app()['cache']-&gt;forget('spatie.permission.cache');</span><br></pre></td></tr></table></figure>
<p><strong>模型动作</strong></p>
<p>在 <code>User</code> 等模型中引入 <code>use Spatie\Permission\Traits\HasRoles</code> 可以拥有所有权限操作方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">Spatie</span>\<span class="title">Permission</span>\<span class="title">Traits</span>\<span class="title">HasRoles</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span> <span class="keyword">extends</span> <span class="title">Authenticatable</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">HasRoles</span>;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>新建角色</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">Spatie</span>\<span class="title">Permission</span>\<span class="title">Models</span>\<span class="title">Role</span>;</span><br><span class="line">$role = Role::create([<span class="string">'name'</span> =&gt; <span class="string">'admin'</span>]);</span><br></pre></td></tr></table></figure>
<p><strong>删除角色</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;removeRole(<span class="string">'writer'</span>);</span><br></pre></td></tr></table></figure>
<p>角色也可以同步：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//所有当前角色将从用户中删除，并替换为给定的数组中的角色</span></span><br><span class="line">$user-&gt;syncRoles([<span class="string">'writer'</span>, <span class="string">'admin'</span>]);</span><br></pre></td></tr></table></figure>
<p><strong>添加权限</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> <span class="title">Spatie</span>\<span class="title">Permission</span>\<span class="title">Models</span>\<span class="title">Permission</span>;</span><br><span class="line"></span><br><span class="line">Permission::create([<span class="string">'name'</span> =&gt; <span class="string">'edit_articles'</span>]);</span><br><span class="line">$role-&gt;givePermissionTo(<span class="string">'edit_articles'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">#或者使用下面分配权限</span></span><br><span class="line">$permission-&gt;assignRole($role);</span><br></pre></td></tr></table></figure>
<p>可以使用以下方法之一将多个权限同步到一个角色：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$role-&gt;syncPermissions($permissions);</span><br><span class="line">$permission-&gt;syncRoles($roles);</span><br></pre></td></tr></table></figure>
<p><strong>删除权限</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$role-&gt;revokePermissionTo($permission);</span><br><span class="line">$permission-&gt;removeRole($role);</span><br></pre></td></tr></table></figure>
<p>一次性撤消并添加新的权限：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;syncPermissions([<span class="string">'edit articles'</span>, <span class="string">'delete articles'</span>]);</span><br></pre></td></tr></table></figure>
<p><strong>添加用户角色</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 单个角色</span></span><br><span class="line">$user-&gt;assignRole(<span class="string">'admin'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 数组形式的多个角色</span></span><br><span class="line">$user-&gt;assignRole([<span class="string">'super_user'</span>, <span class="string">'admin'</span>]);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 同步角色(不存在添加，存在忽略)</span></span><br><span class="line">auth()-&gt;user()-&gt;syncRoles([<span class="string">'admin'</span>]);</span><br></pre></td></tr></table></figure>
<p><strong>添加用户权限</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 为用户添加『直接权限』</span></span><br><span class="line">$user-&gt;givePermissionTo(<span class="string">'manage_contents'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取所有直接权限</span></span><br><span class="line">$user-&gt;getDirectPermissions()</span><br></pre></td></tr></table></figure>
<p><strong>检查用户角色</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 是否是超级管理员</span></span><br><span class="line">$user-&gt;hasRole(<span class="string">'super_user'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 拥有多个角色中的一个角色</span></span><br><span class="line">$user-&gt;hasAnyRole(Role::all());</span><br><span class="line"></span><br><span class="line"><span class="comment">// 包含所有角色</span></span><br><span class="line">$user-&gt;hasAllRoles(Role::all());</span><br></pre></td></tr></table></figure>
<p><strong>检查权限</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//用户是否拥有权限</span></span><br><span class="line">$user-&gt;can(<span class="string">'edit_articles'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//角色是否拥有权限</span></span><br><span class="line">$role-&gt;hasPermissionTo(<span class="string">'edit_articles'</span>);</span><br></pre></td></tr></table></figure>
<p>或者你可以传递一个代表权限 ID 的整数</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;hasPermissionTo(<span class="string">'1'</span>);</span><br><span class="line">$user-&gt;hasPermissionTo(Permission::find(<span class="number">1</span>)-&gt;id);</span><br><span class="line">$user-&gt;hasPermissionTo($somePermission-&gt;id);</span><br></pre></td></tr></table></figure>
<p>如果用户有任何一个权限即通过：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;hasAnyPermission([<span class="string">'edit articles'</span>, <span class="string">'publish articles'</span>, <span class="string">'unpublish articles'</span>]);</span><br></pre></td></tr></table></figure>
<p>用户必须拥有所有权限时通过：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;hasAllPermissions([<span class="string">'edit articles'</span>, <span class="string">'publish articles'</span>, <span class="string">'unpublish articles'</span>]);</span><br></pre></td></tr></table></figure>
<p>你也可以传递整数以通过权限 ID 进行查找</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;hasAnyPermission([<span class="string">'edit articles'</span>, <span class="number">1</span>, <span class="number">5</span>]);</span><br></pre></td></tr></table></figure>
<p>使用 Laravel 默认的 <code>can</code> 功能测试用户是否拥有权限：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;can(<span class="string">'edit articles'</span>);</span><br></pre></td></tr></table></figure>
<p><strong>获取用户权限</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//获取直接分配给用户的所有权限的列表</span></span><br><span class="line">$permissions = $user-&gt;getDirectPermissions();</span><br><span class="line"></span><br><span class="line"><span class="comment">//从用户角色继承的权限</span></span><br><span class="line">$user-&gt;getPermissionsViaRoles();</span><br><span class="line"></span><br><span class="line"><span class="comment">//适用于用户的所有权限（继承和直接）</span></span><br><span class="line">$permissions = $user-&gt;getAllPermissions();</span><br></pre></td></tr></table></figure>
<p><strong>获取用户角色</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$roles = $user-&gt;getRoleNames(); <span class="comment">// 返回一个集合</span></span><br></pre></td></tr></table></figure>
<p><strong>根据权限或角色获取用户</strong></p>
<p><code>HasRoles</code> 特征(trait)还为您的模型添加了一个“角色”范围，以便将查询范围限定为某些角色或权限：</p>
<p>仅返回具有角色 'writer' 的用户</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$users = User::role(<span class="string">'writer'</span>)-&gt;get();</span><br></pre></td></tr></table></figure>
<p>仅返回具有 'edit articles' （继承或直接）权限的用户</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$users = User::permission(<span class="string">'edit articles'</span>)-&gt;get();</span><br></pre></td></tr></table></figure>
<p><strong>Blade 和角色</strong></p>
<p>测试一个特定的角色：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">@role(&apos;writer&apos;)</span><br><span class="line">    I am a writer!</span><br><span class="line">@else</span><br><span class="line">    I am not a writer...</span><br><span class="line">@endrole</span><br></pre></td></tr></table></figure>
<p>同上</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">@hasrole(&apos;writer&apos;)</span><br><span class="line">    I am a writer!</span><br><span class="line">@else</span><br><span class="line">    I am not a writer...</span><br><span class="line">@endhasrole</span><br></pre></td></tr></table></figure>
<p><strong>测试列表中的任何角色：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@hasanyrole($collectionOfRoles)</span><br><span class="line">    I have one or more of these roles!</span><br><span class="line">@else</span><br><span class="line">    I have none of these roles...</span><br><span class="line">@endhasanyrole</span><br><span class="line">// or</span><br><span class="line">@hasanyrole(&apos;writer|admin&apos;)</span><br><span class="line">    I am either a writer or an admin or both!</span><br><span class="line">@else</span><br><span class="line">    I have none of these roles...</span><br><span class="line">@endhasanyrole</span><br></pre></td></tr></table></figure>
<p><strong>测试所有角色：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@hasallroles($collectionOfRoles)</span><br><span class="line">    I have all of these roles!</span><br><span class="line">@else</span><br><span class="line">    I do not have all of these roles...</span><br><span class="line">@endhasallroles</span><br><span class="line">// or</span><br><span class="line">@hasallroles(&apos;writer|admin&apos;)</span><br><span class="line">    I am both a writer and an admin!</span><br><span class="line">@else</span><br><span class="line">    I do not have all of these roles...</span><br><span class="line">@endhasallroles</span><br></pre></td></tr></table></figure>
<p><strong>Blade 和权限</strong></p>
<p>此软件包不会添加任何特定于权限的 Blade 指令。 因此，使用 Laravel 原生的 <code>@can</code> 指令来检查用户是否具有某种权限。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@can(&apos;edit articles&apos;)</span><br><span class="line">  //</span><br><span class="line">@endcan</span><br></pre></td></tr></table></figure>
<p>or</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@if(auth()-&gt;user()-&gt;can(&apos;edit articles&apos;) &amp;&amp; $some_other_condition)</span><br><span class="line">  //</span><br><span class="line">@endif</span><br></pre></td></tr></table></figure>
<h2 id="图片处理">图片处理</h2>
<h3 id="spatie-image">spatie/image</h3>
<p><a href="https://docs.spatie.be/image/v1/usage/basic-usage" target="_blank" rel="noopener">https://docs.spatie.be/image/v1/usage/basic-usage</a> 用于提供丰富的图片处理方式</p>
<h3 id="intervention-image">Intervention/image</h3>
<p><a href="https://github.com/Intervention/image" target="_blank" rel="noopener">https://github.com/Intervention/image</a> 用于裁切缩放等图片处理操作</p>
<p>安装</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ composer <span class="keyword">require</span> intervention/image</span><br><span class="line">$ php artisan vendor:publish --provider=<span class="string">"Intervention\Image\ImageServiceProviderLaravel5"</span></span><br></pre></td></tr></table></figure>
<p>使用</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$img = Image::make(<span class="string">'public/foo.jpg'</span>);</span><br><span class="line"><span class="comment">//只设置高亮标准</span></span><br><span class="line">$img-&gt;resize(<span class="keyword">null</span>, <span class="number">400</span>, <span class="function"><span class="keyword">function</span> <span class="params">($constraint)</span> </span>&#123;</span><br><span class="line">	<span class="comment">//维护比例</span></span><br><span class="line">    $constraint-&gt;aspectRatio();</span><br><span class="line">    <span class="comment">//防止变大</span></span><br><span class="line">    $constraint-&gt;upsize();</span><br><span class="line">&#125;);</span><br><span class="line">$img-&gt;save($file);</span><br></pre></td></tr></table></figure>
<h3 id="spatie-image-v2">spatie/image</h3>
<p><a href="https://github.com/spatie/image" target="_blank" rel="noopener">https://github.com/spatie/image</a></p>
<h2 id="日期处理">日期处理</h2>
<p><a href="https://carbon.nesbot.com/" target="_blank" rel="noopener">https://carbon.nesbot.com/</a> 无需安装 Laravel 已经内置。</p>
<p>中文文档：<a href="https://segmentfault.com/a/1190000012716974#articleHeader2" target="_blank" rel="noopener">https://segmentfault.com/a/1190000012716974#articleHeader2</a></p>
<p>下面是中文本地化的设置：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$user-&gt;created_at-&gt;diffForHumans()</span><br></pre></td></tr></table></figure>
<p>在 <code>app/Providers/AppServiceProvider.php</code> 的 <code>boot</code>方法中设置：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">\Carbon\Carbon::setLocale(<span class="string">'zh'</span>);</span><br></pre></td></tr></table></figure>
<h2 id="debugbar">Debugbar</h2>
<p><a href="https://github.com/barryvdh/laravel-debugbar" target="_blank" rel="noopener">https://github.com/barryvdh/laravel-debugbar</a></p>
<p><strong>安装</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require barryvdh/laravel-debugbar --dev</span><br></pre></td></tr></table></figure>
<p>修改 <code>.env</code> 配置文件</p>
<figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">DEBUGBAR_ENABLED</span>=<span class="literal">true</span></span><br></pre></td></tr></table></figure>
<h2 id="模块化设计">模块化设计</h2>
<p><a href="https://nwidart.com/laravel-modules/v6/introduction" target="_blank" rel="noopener">https://nwidart.com/laravel-modules/v6/introduction</a></p>
<p><a href="https://github.com/houdunwang/laravel-module" target="_blank" rel="noopener">https://github.com/houdunwang/laravel-module</a></p>
<h3 id="组件介绍">组件介绍</h3>
<p>通过使用模块来管理大型 Laravel 项目，模块就像一个 laravel 包非常方便的进行添加或移除。</p>
<p><code>nwidart/laravel-modules</code>是一个 Laravel 软件包，创建该软件包是为了使用模块管理大型 Laravel 应用。模块就像 Laravel 包一样，它具有一些视图，控制器或模型。Laravel 5 支持并测试了该软件包。</p>
<p>此软件包是<a href="https://github.com/pingpong-labs/modules" target="_blank" rel="noopener">pingpong / modules</a>的重新发布，重新组织和维护的版本，不再维护。该软件包在<a href="https://asgardcms.com/" target="_blank" rel="noopener">AsgardCMS 中使用</a>。</p>
<p>原始软件包没有的一大额外奖励：<strong>tests</strong>。</p>
<p><strong>注意：</strong></p>
<p>如果从以前的版本升级到 v6，请运行以下命令：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan module:v6:migrate</span><br></pre></td></tr></table></figure>
<h3 id="安装组件-v3">安装组件</h3>
<p>要通过 Composer 安装，运行以下命令</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require nwidart/laravel-modules</span><br></pre></td></tr></table></figure>
<p>通过运行以下命令来发布程序包的配置文件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan vendor:publish --provider=&quot;Nwidart\Modules\LaravelModulesServiceProvider&quot;</span><br></pre></td></tr></table></figure>
<h3 id="自动加载">自动加载</h3>
<p>默认情况下，模块类不会自动加载。您可以使用来自动加载模块<code>psr-4</code></p>
<p><strong>composer.json</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">"autoload"</span>: &#123;</span><br><span class="line">    <span class="string">"psr-4"</span>: &#123;</span><br><span class="line">      <span class="string">"App\\"</span>: <span class="string">"app/"</span>,</span><br><span class="line">      <span class="string">"Modules\\"</span>: <span class="string">"Modules/"</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="创建模块">创建模块</h3>
<p>运行以下命令创建模块</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan module:make &lt;module-name&gt;</span><br></pre></td></tr></table></figure>
<p>也可以在一个命令中创建多个模块</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan module:make Blog User Auth</span><br></pre></td></tr></table></figure>
<p>默认情况下，当您创建新模块时，该命令将自动添加一些资源，例如控制器，种子类，服务提供者等。如果您不需要这些，则可以添加<code>--plain</code>标志，以生成普通模块</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">php artisan module:make Blog --plain</span><br><span class="line"># or</span><br><span class="line">php artisan module:make Blog -p</span><br></pre></td></tr></table></figure>
<h2 id="webpack">webpack</h2>
<p>laravel 前端使用 webpack 工具构建，我们介绍几个常用动作</p>
<p>复制目录</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mix.copyDirectory(<span class="string">'assets/img'</span>, <span class="string">'public/img'</span>);</span><br></pre></td></tr></table></figure>
<h2 id="doctrine-dbal">Doctrine/dbal</h2>
<p>dbal 是用于管理数据表结构的组件库。</p>
<p>在线文档：<a href="https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-manager.html#schema-manager" target="_blank" rel="noopener">https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-manager.html#schema-manager</a></p>
<h2 id="active-状态">Active 状态</h2>
<p>在我们构建页面的过程中，经常会根据 url 的参数设置页面元素的 <code>active</code> 属性，将其渲染为「选中」状态。</p>
<p>官网 <a href="https://www.hieule.info/products/laravel-active-version-3-released" target="_blank" rel="noopener">https://www.hieule.info/products/laravel-active-version-3-released</a></p>
<p><strong>安装</strong></p>
<p>Require this package as your dependencies:</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require hieu-le/active</span><br></pre></td></tr></table></figure>
<p>Append this line to your <code>providers</code> array in <code>config/app.php</code></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HieuLe\Active\ActiveServiceProvider::class,</span><br></pre></td></tr></table></figure>
<p>Append this line to your <code>aliases</code> array in <code>config/app.php</code></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'Active'</span> =&gt; HieuLe\Active\Facades\Active::class,</span><br></pre></td></tr></table></figure>
<p><strong>语法</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">active_class</span><span class="params">($condition, $activeClass = <span class="string">'active'</span>, $inactiveClass = <span class="string">''</span>)</span></span></span><br></pre></td></tr></table></figure>
<p><strong>使用</strong></p>
<p>此扩展包提供了一批函数让我们更方便的进行 <code>$condition</code> 判断：</p>
<ol>
<li>if_uri() - 判断当前的 url 是否满足指定的 url；</li>
<li>if_uri_pattern() - 判断当前的 url 是否含有指定的字符；</li>
<li>if_query() - 判断指定的 GET 变量是否符合设置的值；</li>
<li>if_route() - 判断当前对应的路由是否是指定的路由；</li>
<li>if_route_pattern() - 判断当前的路由是否包含指定的字符；</li>
<li>if_route_param() - 判断当前的 url 有无指定的路由参数。</li>
</ol>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;a class=&quot;&#123;&#123; active_class(if_route(&apos;users.index&apos;)) &#125;&#125;&quot; href=&quot;&quot;&gt;会员&lt;/a&gt;</span><br><span class="line"></span><br><span class="line">&lt;a class=&quot;&#123;&#123; active_class(if_route(&apos;cateogry.show&apos;) &amp;&amp; if_route_param(&apos;category&apos;, 1)) &#125;&#125;&quot; href=&quot;&quot;&gt;实战&lt;/a&gt;</span><br><span class="line"></span><br><span class="line">&lt;a class=&quot;&#123;&#123; active_class(if_route(&apos;cateogry.show&apos;) &amp;&amp; if_route_param(&apos;category&apos;, 2)) &#125;&#125;&quot; href=&quot;&quot;&gt;阶段&lt;/a&gt;</span><br></pre></td></tr></table></figure>
<h2 id="xss-过滤">XSS 过滤</h2>
<p><a href="https://github.com/mewebstudio/Purifier" target="_blank" rel="noopener">https://github.com/mewebstudio/Purifier</a></p>
<p>安装</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">composer require mews/purifier</span><br><span class="line">php artisan vendor:publish --provider="Mews\Purifier\PurifierServiceProvider"</span><br></pre></td></tr></table></figure>
<p>配置文件</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">config/purifier.php</span><br></pre></td></tr></table></figure>
<p>使用</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">clean(Input::get(<span class="string">'inputname'</span>),<span class="string">'default'</span>);</span><br></pre></td></tr></table></figure>
<h2 id="guzzle">Guzzle</h2>
<p>Guzzle 是一个 PHP 的 HTTP 客户端，用来轻而易举地发送请求，并集成到我们的 WEB 服务上。</p>
<p><a href="http://guzzle-cn.readthedocs.io/zh_CN/latest/" target="_blank" rel="noopener">http://guzzle-cn.readthedocs.io/zh_CN/latest/</a></p>
<h2 id="sudo-su-用户切换">sudo-su 用户切换</h2>
<p><a href="https://github.com/viacreative/sudo-su" target="_blank" rel="noopener">https://github.com/viacreative/sudo-su</a></p>
<p>安装软件包</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require viacreative/sudo-su</span><br></pre></td></tr></table></figure>
<p>Add the package's service provider to your app in your project's <code>AppServiceProvider</code>:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AppServiceProvider</span> <span class="keyword">extends</span> <span class="title">ServiceProvider</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">register</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (config(<span class="string">'app.debug'</span>)) &#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;app-&gt;register(<span class="string">'VIACreative\SudoSu\ServiceProvider'</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>发布</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan vendor:publish</span><br></pre></td></tr></table></figure>
<p><strong>配置</strong></p>
<p>修改配置文件 <code>config/sudosu.php</code> 添加允许使用的域名后缀</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'allowed_tlds'</span> =&gt; [<span class="string">'dev'</span>, <span class="string">'local'</span>,<span class="string">'hd'</span>],</span><br></pre></td></tr></table></figure>
<p><strong>guard</strong></p>
<p>如果用户模型不是 User 也需要在配置文件中修改</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'user_model'</span> =&gt; \Modules\Admin\Entities\Admin::class</span><br></pre></td></tr></table></figure>
<p><strong>使用</strong></p>
<p>在模板中使用</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@if (config(&apos;app.debug&apos;))</span><br><span class="line"> @include(&apos;sudosu::user-selector&apos;)</span><br><span class="line">@endif</span><br></pre></td></tr></table></figure>
<h2 id="simditor-编辑器">simditor 编辑器</h2>
<p>simditor 是一款简单快速的编辑器。</p>
<p><a href="http://simditor.tower.im/" target="_blank" rel="noopener">http://simditor.tower.im/</a></p>
<p>下载 <a href="https://github.com/mycolorway/simditor/archive/v2.3.16.zip" target="_blank" rel="noopener">https://github.com/mycolorway/simditor/archive/v2.3.16.zip</a></p>
<p><strong>配置</strong></p>
<ol>
<li>
<p>复制<code>site/assets/scripts</code> 目录为 Laravel 项目的 <code>resources/plugin/simditor/scripts</code> 目录</p>
</li>
<li>
<p>复制<code>site/assets/styles</code> 目录为 Laravel 项目的 <code>resource/plugin/simditor/styles</code> 目录</p>
</li>
<li>
<p>修改 <code>webpack.mix.js</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.mix.copy(<span class="string">'resources/plugin'</span>,<span class="string">'public/plugin'</span>)</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p><strong>创建控制器</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">artisan make:controller Components/UploadController</span><br></pre></td></tr></table></figure>
<p>下面是控制器内容，使用了 <code>UploadService</code> 服务（参考上面<code>Service 服务化</code> 文档）</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UploadController</span> <span class="keyword">extends</span> <span class="title">Controller</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">editorImage</span><span class="params">(Request $request, UploadService $uploadService)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        $file = $uploadService-&gt;make($request-&gt;upload_file);</span><br><span class="line">        <span class="keyword">return</span> [</span><br><span class="line">            <span class="string">"success"</span>   =&gt; <span class="keyword">true</span>,</span><br><span class="line">            <span class="string">"msg"</span>       =&gt; <span class="string">"上传成功"</span>,</span><br><span class="line">            <span class="string">"file_path"</span> =&gt; $file[<span class="string">'path'</span>],</span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>配置路由</strong></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Route::post(<span class="string">'upload/image'</span>,<span class="string">'Components\UploadController@editorImage'</span>)-&gt;name(<span class="string">'upload.image'</span>);</span><br></pre></td></tr></table></figure>
<p><strong>使用</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">&lt;script type=&quot;text/javascript&quot; src=&quot;&#123;&#123;asset(&apos;js/simditor/module.js&apos;)&#125;&#125;&quot;&gt;&lt;/script&gt;</span><br><span class="line">&lt;script type=&quot;text/javascript&quot; src=&quot;&#123;&#123;asset(&apos;js/simditor/hotkeys.js&apos;)&#125;&#125;&quot;&gt;&lt;/script&gt;</span><br><span class="line">&lt;script type=&quot;text/javascript&quot; src=&quot;&#123;&#123;asset(&apos;js/simditor/uploader.js&apos;)&#125;&#125;&quot;&gt;&lt;/script&gt;</span><br><span class="line">&lt;script type=&quot;text/javascript&quot; src=&quot;&#123;&#123;asset(&apos;js/simditor/simditor.js&apos;)&#125;&#125;&quot;&gt;&lt;/script&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">	$(function () &#123;</span><br><span class="line">		var editor = new Simditor(&#123;</span><br><span class="line">			textarea: $(&apos;#editor&apos;),</span><br><span class="line">			pasteImage: true,</span><br><span class="line">			upload: true,</span><br><span class="line">			upload: &#123;</span><br><span class="line">				url: &apos;&apos;,</span><br><span class="line">				params: &#123;_token: &apos;&#123;&#123; csrf_token() &#125;&#125;&apos;&#125;,</span><br><span class="line">				fileKey: &apos;upload_file&apos;,</span><br><span class="line">				connectionCount: 3,</span><br><span class="line">				leaveConfirm: &apos;文件上传中，关闭此页面将取消上传。&apos;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;);</span><br><span class="line">	&#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>
<h2 id="mailhog">Mailhog</h2>
<p>Mailhog (<code>homestead</code> 已经内置）可以轻松的抓取到你发送的电子邮件并进行检查，而无需将邮件真正发送给收件人. 开始之前, 请更新你的 <code>.env</code> 文件并使用如下邮件设置:</p>
<figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">MAIL_DRIVER</span>=smtp</span><br><span class="line"><span class="attr">MAIL_HOST</span>=localhost</span><br><span class="line"><span class="attr">MAIL_PORT</span>=<span class="number">1025</span></span><br><span class="line"><span class="attr">MAIL_USERNAME</span>=null</span><br><span class="line"><span class="attr">MAIL_PASSWORD</span>=null</span><br><span class="line"><span class="attr">MAIL_ENCRYPTION</span>=null</span><br></pre></td></tr></table></figure>
<p><strong>访问</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://domain:8025</span><br></pre></td></tr></table></figure>
<h2 id="china-area-data">china-area-data</h2>
<p>中国行政区域数据 <a href="https://www.npmjs.com/package/china-area-data" target="_blank" rel="noopener">https://www.npmjs.com/package/china-area-data</a></p>
<h2 id="predis">predis</h2>
<p>redis 队列驱动</p>
<p>Github：<a href="https://github.com/nrk/predis" target="_blank" rel="noopener">https://github.com/nrk/predis</a></p>
<h4 id="安装">安装</h4>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require &quot;predis/predis:~1.0&quot;</span><br></pre></td></tr></table></figure>
<h2 id="判断设备">判断设备</h2>
<p>判断移动、平板设备等场景还是很常见的。</p>
<p>Github：<a href="https://github.com/hisorange/browser-detect" target="_blank" rel="noopener">https://github.com/hisorange/browser-detect</a></p>
<h2 id="宝塔设置">宝塔设置</h2>
<p><strong>域名设置</strong></p>
<p>Laravel 使用 public 目录访问，需要将域名绑定在 public 目录</p>
<p><strong>打包上传</strong></p>
<ol>
<li>将本地 Laravel 项目打成 zip 包</li>
<li>在宝塔中的文件菜单选择你的网站目录，然后上传 zip 文件</li>
<li>上传后解压释放即可</li>
</ol>
<p><strong>伪静态</strong></p>
<p>在网站菜单选择需要修改的网站，进行以下设置</p>
<p><strong>MySQL</strong></p>
<p>宝塔的 mysql 版本低，运行会出错。</p>
<ol>
<li>
<p>先在宝塔后台升级 mysql</p>
</li>
<li>
<p>在 Laravel 的 AppServiceProvider.php 文件里的 boot 方法里设置</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">boot</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"> 	\Schema::defaultStringLength(<span class="number">191</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h2 id="常见错误">常见错误</h2>
<ol>
<li>有时执行 composer 意外中断或卡住，删除 vendor 与 composer.lock 后重新执行</li>
<li>使用模块化开发时模块下的 node_modules 严重影响 composer 执行，可以先删除模块下的 node_modules 再执行 composer install 、composer dumpautoload 等命令</li>
</ol>
<h2 id="swoole-加速">Swoole 加速</h2>
<h3 id="安装-swoole-扩展">安装 Swoole 扩展</h3>
<p>Swoole 扩展到 GitHub 首页下载 Swoole 扩展源码，地址：<a href="https://github.com/swoole/swoole-src" target="_blank" rel="noopener">https://github.com/swoole/swoole-src</a> 下载后按照标准的 PHP 扩展编译方式进行编译和安装。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">unzip swoole-master.zip</span><br><span class="line">/usr/local/php/bin/phpize</span><br><span class="line">./configure --with-php-config=/usr/local/php/bin/php-config</span><br><span class="line">sudo make install</span><br></pre></td></tr></table></figure>
<p>编译安装完后，修改 php.ini 加入 <a href="http://extension=swoole.so" target="_blank" rel="noopener">extension=swoole.so</a> 开启 swoole 扩展</p>
<h3 id="安装-laravel-swoole-组件">安装 laravel-swoole 组件</h3>
<p>组件地址：<a href="https://github.com/swooletw/laravel-swoole" target="_blank" rel="noopener">https://github.com/swooletw/laravel-swoole</a></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require swooletw/laravel-swoole</span><br></pre></td></tr></table></figure>
<p>然后，添加服务提供者：
如果你使用 Laravel ，在 config/app.php 服务提供者数组添加该服务提供者：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">    &apos;providers&apos; =&gt; [</span><br><span class="line">        SwooleTW\Http\LaravelServiceProvider::class,</span><br><span class="line">    ],</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
<h3 id="启动-swoole-服务">启动 swoole 服务</h3>
<p>现在，你可以执行以下的命令来启动 Swoole HTTP 服务。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/php/bin/php artisan swoole:http start</span><br></pre></td></tr></table></figure>
<p>然后你可以看到以下信息：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Starting swoole http server...</span><br><span class="line">Swoole http server started: &lt;http://127.0.0.1:1215&gt;</span><br></pre></td></tr></table></figure>
<p>现在可以通过访问 <a href="http://127.0.0.1:1215" target="_blank" rel="noopener">http://127.0.0.1:1215</a> 来进入 Laravel 应用</p>
<h3 id="laravel-swoole-命令">Laravel-swoole 命令</h3>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 启动</span></span><br><span class="line">/usr/local/php/bin/php artisan swoole:http start</span><br><span class="line"><span class="meta">#</span><span class="bash"> 重启</span></span><br><span class="line">/usr/local/php/bin/php artisan swoole:http restart</span><br><span class="line"><span class="meta">#</span><span class="bash"> 重载</span></span><br><span class="line">/usr/local/php/bin/php artisan swoole:http reload</span><br><span class="line"><span class="meta">#</span><span class="bash"> 停止</span></span><br><span class="line">/usr/local/php/bin/php artisan swoole:http stop</span><br><span class="line"><span class="meta">#</span><span class="bash"> 查看服务信息</span></span><br><span class="line">/usr/local/php/bin/php artisan swoole:http infos</span><br></pre></td></tr></table></figure>
<h3 id="配合-ngnix-使用">配合 Ngnix 使用</h3>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">gzip</span> <span class="literal">on</span>;</span><br><span class="line"><span class="attribute">gzip_min_length</span> <span class="number">1024</span>;</span><br><span class="line"><span class="attribute">gzip_comp_level</span> <span class="number">2</span>;</span><br><span class="line"><span class="attribute">gzip_types</span> text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;</span><br><span class="line"><span class="attribute">gzip_vary</span> <span class="literal">on</span>;</span><br><span class="line"><span class="attribute">gzip_disable</span> <span class="string">"msie6"</span>;</span><br><span class="line"><span class="attribute">upstream</span> labs &#123;</span><br><span class="line">    <span class="comment"># Connect IP:Port</span></span><br><span class="line">    <span class="attribute">server</span> <span class="number">127.0.0.1:1215</span> weight=<span class="number">5</span> max_fails=<span class="number">3</span> fail_timeout=<span class="number">30s</span>;</span><br><span class="line">    <span class="attribute">keepalive</span> <span class="number">16</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">server_name</span> www.xxx.com;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">root</span> /data/www/labs/public/;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">access_log</span>  /var/log/nginx/xxx.cn.access.log main;</span><br><span class="line">    <span class="attribute">error_log</span>   /var/log/nginx/xxx.cn.<span class="literal">error</span>.log;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">autoindex</span> <span class="literal">off</span>;</span><br><span class="line">    <span class="attribute">index</span> index.html index.htm;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">location</span> / &#123;</span><br><span class="line">        <span class="attribute">try_files</span> <span class="variable">$uri</span> <span class="variable">@laravels</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">location</span> <span class="variable">@laravels</span> &#123;</span><br><span class="line">        <span class="comment"># proxy_connect_timeout 60s;</span></span><br><span class="line">        <span class="comment"># proxy_send_timeout 60s;</span></span><br><span class="line">        <span class="comment"># proxy_read_timeout 120s;</span></span><br><span class="line">        <span class="attribute">proxy_http_version</span> <span class="number">1</span>.<span class="number">1</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Connection <span class="string">""</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Real-PORT <span class="variable">$remote_port</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Host <span class="variable">$http_host</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Scheme <span class="variable">$scheme</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Server-Protocol <span class="variable">$server_protocol</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Server-Name <span class="variable">$server_name</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Server-Addr <span class="variable">$server_addr</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Server-Port <span class="variable">$server_port</span>;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://labs;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="artisan-命令">Artisan 命令</h2>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:controller HomeController</span><br></pre></td></tr></table></figure>

      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>坚持原创技术分享，您的支持将鼓励我继续创作！</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/images/wpay.png" alt="King 微信支付">
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/images/alipay.jpg" alt="King 支付宝">
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    
      <div>
        <ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者：</strong>
    King
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://zhongxc.cc/d1159936.html" title="Laravel">https://zhongxc.cc/d1159936.html</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>
    本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明出处！
  </li>
</ul>

      </div>
    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/Laravel/" rel="tag"># Laravel</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/f1936d0b.html" rel="next" title="git创建分支并推送到远程">
                <i class="fa fa-chevron-left"></i> git创建分支并推送到远程
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/7fd38f80.html" rel="prev" title="ElasticSearch 删除所有数据">
                ElasticSearch 删除所有数据 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          
            <img class="site-author-image" itemprop="image" src="/assets/images/avatar.jpg" alt="King">
          
            <p class="site-author-name" itemprop="name">King</p>
            <p class="site-description motion-element" itemprop="description"></p>
        </div>

        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
            
              <a href="/archives/">
            
                <span class="site-state-item-count">61</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">16</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">34</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        
          <div class="feed-link motion-element">
            <a href="/atom.xml" rel="alternate">
              <i class="fa fa-rss"></i>
              RSS
            </a>
          </div>
        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/crytostring" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i></a>
              </span>
            
              <span class="links-of-author-item">
                <a href="mailto:cqzhongxc@outlook.com" target="_blank" title="E-Mail">
                  
                    <i class="fa fa-fw fa-envelope"></i></a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://gitee.com/ikings" target="_blank" title="gitee">
                  
                    <i class="fa fa-fw fa-git"></i></a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.stephen520.cn" target="_blank" title="石鹏">
                  
                    <i class="fa fa-fw fa-scribd"></i></a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.tutorialspoint.com/index.htm" target="_blank" title="tutorialspoint">
                  
                    <i class="fa fa-fw fa-tumblr"></i></a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://leetcode-cn.com/interview" target="_blank" title="leetcode">
                  
                    <i class="fa fa-fw fa-code"></i></a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.geeksforgeeks.org/php-addcslashes-function" target="_blank" title="geeksforgeeks">
                  
                    <i class="fa fa-fw fa-diamond"></i></a>
              </span>
            
          
        </div>

        
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#null"><span class="nav-number">1.</span> <span class="nav-text">Laravel</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#api"><span class="nav-number">1.1.</span> <span class="nav-text">Api</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#动作"><span class="nav-number">1.1.1.</span> <span class="nav-text">动作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#命名"><span class="nav-number">1.1.2.</span> <span class="nav-text">命名</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#版本"><span class="nav-number">1.1.3.</span> <span class="nav-text">版本</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#过滤"><span class="nav-number">1.1.4.</span> <span class="nav-text">过滤</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#状态码"><span class="nav-number">1.1.5.</span> <span class="nav-text">状态码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#响应格式"><span class="nav-number">1.1.6.</span> <span class="nav-text">响应格式</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#postman"><span class="nav-number">1.2.</span> <span class="nav-text">Postman</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#dingo"><span class="nav-number">1.3.</span> <span class="nav-text">Dingo</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装组件"><span class="nav-number">1.3.1.</span> <span class="nav-text">安装组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#配置说明"><span class="nav-number">1.3.2.</span> <span class="nav-text">配置说明</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#接口版本"><span class="nav-number">1.3.3.</span> <span class="nav-text">接口版本</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#基础控制器"><span class="nav-number">1.3.4.</span> <span class="nav-text">基础控制器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#transformers"><span class="nav-number">1.3.5.</span> <span class="nav-text">Transformers</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#基本使用"><span class="nav-number">1.3.5.1.</span> <span class="nav-text">基本使用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#include"><span class="nav-number">1.3.5.2.</span> <span class="nav-text">include</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#响应结果"><span class="nav-number">1.3.6.</span> <span class="nav-text">响应结果</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#限制请求数"><span class="nav-number">1.3.7.</span> <span class="nav-text">限制请求数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#身份验证"><span class="nav-number">1.3.8.</span> <span class="nav-text">身份验证</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#jwt"><span class="nav-number">1.4.</span> <span class="nav-text">Jwt</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装组件-v2"><span class="nav-number">1.4.1.</span> <span class="nav-text">安装组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#配置说明-v2"><span class="nav-number">1.4.2.</span> <span class="nav-text">配置说明</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#更新用户模型"><span class="nav-number">1.4.3.</span> <span class="nav-text">更新用户模型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#配置验证守卫"><span class="nav-number">1.4.4.</span> <span class="nav-text">配置验证守卫</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#验证操作"><span class="nav-number">1.4.5.</span> <span class="nav-text">验证操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#使用令牌"><span class="nav-number">1.4.6.</span> <span class="nav-text">使用令牌</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#laravel"><span class="nav-number">1.5.</span> <span class="nav-text">Laravel</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#介绍"><span class="nav-number">1.6.</span> <span class="nav-text">介绍</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#版本-v2"><span class="nav-number">1.7.</span> <span class="nav-text">版本</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#全新安装"><span class="nav-number">1.8.</span> <span class="nav-text">全新安装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#mysql-低版本"><span class="nav-number">1.9.</span> <span class="nav-text">MySQL 低版本</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#下载团队项目"><span class="nav-number">1.10.</span> <span class="nav-text">下载团队项目</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#基本使用-v2"><span class="nav-number">1.11.</span> <span class="nav-text">基本使用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#视图"><span class="nav-number">1.12.</span> <span class="nav-text">视图</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#脚手架"><span class="nav-number">1.13.</span> <span class="nav-text">脚手架</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#路由别名"><span class="nav-number">1.14.</span> <span class="nav-text">路由别名</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#数据迁移"><span class="nav-number">1.15.</span> <span class="nav-text">数据迁移</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模型"><span class="nav-number">1.16.</span> <span class="nav-text">模型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#登录历史跳转"><span class="nav-number">1.17.</span> <span class="nav-text">登录历史跳转</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#分页"><span class="nav-number">1.18.</span> <span class="nav-text">分页</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#监听-sql"><span class="nav-number">1.19.</span> <span class="nav-text">监听 SQL</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#tinker"><span class="nav-number">1.20.</span> <span class="nav-text">TINKER</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#路由参数"><span class="nav-number">1.21.</span> <span class="nav-text">路由参数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#隐性路由模型绑定"><span class="nav-number">1.22.</span> <span class="nav-text">隐性路由模型绑定</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#资源控制器"><span class="nav-number">1.23.</span> <span class="nav-text">资源控制器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#表单验证"><span class="nav-number">1.24.</span> <span class="nav-text">表单验证</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#表单函数"><span class="nav-number">1.25.</span> <span class="nav-text">表单函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#表单请求验证"><span class="nav-number">1.26.</span> <span class="nav-text">表单请求验证</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#重定向"><span class="nav-number">1.27.</span> <span class="nav-text">重定向</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#闪存数据"><span class="nav-number">1.28.</span> <span class="nav-text">闪存数据</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#登录验证"><span class="nav-number">1.29.</span> <span class="nav-text">登录验证</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模型事件"><span class="nav-number">1.30.</span> <span class="nav-text">模型事件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#权限策略"><span class="nav-number">1.31.</span> <span class="nav-text">权限策略</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#邮件"><span class="nav-number">1.32.</span> <span class="nav-text">邮件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#集合"><span class="nav-number">1.33.</span> <span class="nav-text">集合</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#多对多关联"><span class="nav-number">1.34.</span> <span class="nav-text">多对多关联</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#消息通知"><span class="nav-number">1.35.</span> <span class="nav-text">消息通知</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#创建通知"><span class="nav-number">1.35.1.</span> <span class="nav-text">创建通知</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数据库通知"><span class="nav-number">1.35.2.</span> <span class="nav-text">数据库通知</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#邮件通知"><span class="nav-number">1.35.3.</span> <span class="nav-text">邮件通知</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#发送通知"><span class="nav-number">1.35.4.</span> <span class="nav-text">发送通知</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#队列化通知"><span class="nav-number">1.35.5.</span> <span class="nav-text">队列化通知</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#自定义函数"><span class="nav-number">1.36.</span> <span class="nav-text">自定义函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#redis"><span class="nav-number">1.37.</span> <span class="nav-text">Redis</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#队列"><span class="nav-number">1.38.</span> <span class="nav-text">队列</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#supervisor"><span class="nav-number">1.39.</span> <span class="nav-text">Supervisor</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#repository"><span class="nav-number">1.40.</span> <span class="nav-text">Repository</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#service-服务化"><span class="nav-number">1.41.</span> <span class="nav-text">Service 服务化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#任务调度"><span class="nav-number">1.42.</span> <span class="nav-text">任务调度</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#laravel-plugin"><span class="nav-number">1.43.</span> <span class="nav-text">Laravel Plugin</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#laravel-ide-helper"><span class="nav-number">1.44.</span> <span class="nav-text">laravel-ide-helper</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#多语言"><span class="nav-number">1.45.</span> <span class="nav-text">多语言</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#session"><span class="nav-number">1.46.</span> <span class="nav-text">SESSION</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#验证码"><span class="nav-number">1.47.</span> <span class="nav-text">验证码</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#用户认证"><span class="nav-number">1.48.</span> <span class="nav-text">用户认证</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#重定向未认证用户"><span class="nav-number">1.48.1.</span> <span class="nav-text">重定向未认证用户</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#事件"><span class="nav-number">1.48.2.</span> <span class="nav-text">事件</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#异常处理-excepton"><span class="nav-number">1.49.</span> <span class="nav-text">异常处理 Excepton</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#创建异常类"><span class="nav-number">1.49.1.</span> <span class="nav-text">创建异常类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#异常日志"><span class="nav-number">1.49.2.</span> <span class="nav-text">异常日志</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#全站动态"><span class="nav-number">1.50.</span> <span class="nav-text">全站动态</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#记录动态"><span class="nav-number">1.50.1.</span> <span class="nav-text">记录动态</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#记录模型事件"><span class="nav-number">1.50.2.</span> <span class="nav-text">记录模型事件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自定义要记录的事件"><span class="nav-number">1.50.3.</span> <span class="nav-text">自定义要记录的事件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自定义日志名称"><span class="nav-number">1.50.4.</span> <span class="nav-text">自定义日志名称</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#markdown-转-html"><span class="nav-number">1.51.</span> <span class="nav-text">Markdown 转 HTML</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#角色权限"><span class="nav-number">1.52.</span> <span class="nav-text">角色权限</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#图片处理"><span class="nav-number">1.53.</span> <span class="nav-text">图片处理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#spatie-image"><span class="nav-number">1.53.1.</span> <span class="nav-text">spatie/image</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#intervention-image"><span class="nav-number">1.53.2.</span> <span class="nav-text">Intervention/image</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#spatie-image-v2"><span class="nav-number">1.53.3.</span> <span class="nav-text">spatie/image</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#日期处理"><span class="nav-number">1.54.</span> <span class="nav-text">日期处理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#debugbar"><span class="nav-number">1.55.</span> <span class="nav-text">Debugbar</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模块化设计"><span class="nav-number">1.56.</span> <span class="nav-text">模块化设计</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#组件介绍"><span class="nav-number">1.56.1.</span> <span class="nav-text">组件介绍</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#安装组件-v3"><span class="nav-number">1.56.2.</span> <span class="nav-text">安装组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自动加载"><span class="nav-number">1.56.3.</span> <span class="nav-text">自动加载</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#创建模块"><span class="nav-number">1.56.4.</span> <span class="nav-text">创建模块</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#webpack"><span class="nav-number">1.57.</span> <span class="nav-text">webpack</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#doctrine-dbal"><span class="nav-number">1.58.</span> <span class="nav-text">Doctrine/dbal</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#active-状态"><span class="nav-number">1.59.</span> <span class="nav-text">Active 状态</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#xss-过滤"><span class="nav-number">1.60.</span> <span class="nav-text">XSS 过滤</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#guzzle"><span class="nav-number">1.61.</span> <span class="nav-text">Guzzle</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#sudo-su-用户切换"><span class="nav-number">1.62.</span> <span class="nav-text">sudo-su 用户切换</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#simditor-编辑器"><span class="nav-number">1.63.</span> <span class="nav-text">simditor 编辑器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#mailhog"><span class="nav-number">1.64.</span> <span class="nav-text">Mailhog</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#china-area-data"><span class="nav-number">1.65.</span> <span class="nav-text">china-area-data</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#predis"><span class="nav-number">1.66.</span> <span class="nav-text">predis</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#安装"><span class="nav-number">1.66.0.1.</span> <span class="nav-text">安装</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#判断设备"><span class="nav-number">1.67.</span> <span class="nav-text">判断设备</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#宝塔设置"><span class="nav-number">1.68.</span> <span class="nav-text">宝塔设置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#常见错误"><span class="nav-number">1.69.</span> <span class="nav-text">常见错误</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#swoole-加速"><span class="nav-number">1.70.</span> <span class="nav-text">Swoole 加速</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-swoole-扩展"><span class="nav-number">1.70.1.</span> <span class="nav-text">安装 Swoole 扩展</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-laravel-swoole-组件"><span class="nav-number">1.70.2.</span> <span class="nav-text">安装 laravel-swoole 组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#启动-swoole-服务"><span class="nav-number">1.70.3.</span> <span class="nav-text">启动 swoole 服务</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#laravel-swoole-命令"><span class="nav-number">1.70.4.</span> <span class="nav-text">Laravel-swoole 命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#配合-ngnix-使用"><span class="nav-number">1.70.5.</span> <span class="nav-text">配合 Ngnix 使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#artisan-命令"><span class="nav-number">1.71.</span> <span class="nav-text">Artisan 命令</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">
  
  &copy;  2020 &mdash; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-random"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">King</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动</div>

  <span class="post-meta-divider">|</span>

  <div class="theme-info">主题 &mdash; <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">NexT.Mist</a> v5.1.2</div>


        
<div class="busuanzi-count">
  <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      <i class="fa fa-user"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      
    </span>
  

  
    <span class="site-pv">
      <i class="fa fa-eye"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      
    </span>
  
</div>








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.2"></script>



  
  

  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.2"></script>


  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.2"></script>



  

  






  




	





  








  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('3');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  

  

  

  
  <script type="text/javascript" src="/js/src/exturl.js?v=5.1.2"></script>


</body>
</html>
